home *** CD-ROM | disk | FTP | other *** search
/ Aminet 48 / Aminet 48 (2002)(GTI - Schatztruhe)[!][Apr 2002].iso / Aminet / text / edit / vim60src.lha / Vim / vim60 / src / ex_cmds.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-09-21  |  131.2 KB  |  5,584 lines

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved    by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  * See README.txt for an overview of the Vim source code.
  8.  */
  9.  
  10. /*
  11.  * ex_cmds.c: some functions for command line commands
  12.  */
  13.  
  14. #include "vim.h"
  15. #include "version.h"
  16.  
  17. #ifdef FEAT_EX_EXTRA
  18. static int linelen __ARGS((int *has_tab));
  19. #endif
  20. static void do_filter __ARGS((linenr_T line1, linenr_T line2, exarg_T *eap, char_u *cmd, int do_in, int do_out));
  21. #ifdef FEAT_VIMINFO
  22. static char_u *viminfo_filename __ARGS((char_u    *));
  23. static void do_viminfo __ARGS((FILE *fp_in, FILE *fp_out, int want_info, int want_marks, int force_read));
  24. static int viminfo_encoding __ARGS((vir_T *virp));
  25. static int read_viminfo_up_to_marks __ARGS((vir_T *virp, int forceit, int writing));
  26. #endif
  27.  
  28. static int check_overwrite __ARGS((exarg_T *eap, buf_T *buf, char_u *fname, char_u *ffname, int other));
  29. static int check_readonly __ARGS((int *forceit, buf_T *buf));
  30. #ifdef FEAT_AUTOCMD
  31. static void delbuf_msg __ARGS((char_u *name));
  32. #endif
  33. static int do_sub_msg __ARGS((void));
  34. static int
  35. #ifdef __BORLANDC__
  36.     _RTLENTRYF
  37. #endif
  38.     help_compare __ARGS((const void *s1, const void *s2));
  39.  
  40. /*
  41.  * ":ascii" and "ga".
  42.  */
  43. /*ARGSUSED*/
  44.     void
  45. do_ascii(eap)
  46.     exarg_T    *eap;
  47. {
  48.     int        c;
  49.     char    buf1[20];
  50.     char    buf2[20];
  51.     char_u    buf3[7];
  52. #ifdef FEAT_MBYTE
  53.     int        c1 = 0;
  54.     int        c2 = 0;
  55.     int        len;
  56.  
  57.     if (enc_utf8)
  58.     c = utfc_ptr2char(ml_get_cursor(), &c1, &c2);
  59.     else
  60. #endif
  61.     c = gchar_cursor();
  62.     if (c == NUL)
  63.     {
  64.     MSG("NUL");
  65.     return;
  66.     }
  67.  
  68. #ifdef FEAT_MBYTE
  69.     IObuff[0] = NUL;
  70.     if (!has_mbyte || (enc_dbcs != 0 && c < 0x100) || c < 0x80)
  71. #endif
  72.     {
  73.     if (c == NL)        /* NUL is stored as NL */
  74.         c = NUL;
  75.     if (vim_isprintc_strict(c) && (c < ' '
  76. #ifndef EBCDIC
  77.             || c > '~'
  78. #endif
  79.                    ))
  80.     {
  81.         transchar_nonprint(buf3, c);
  82.         sprintf(buf1, "  <%s>", (char *)buf3);
  83.     }
  84.     else
  85.         buf1[0] = NUL;
  86. #ifndef EBCDIC
  87.     if (c >= 0x80)
  88.         sprintf(buf2, "  <M-%s>", transchar(c & 0x7f));
  89.     else
  90. #endif
  91.         buf2[0] = NUL;
  92.     sprintf((char *)IObuff, _("<%s>%s%s  %d,  Hex %02x,  Octal %03o"),
  93.         transchar(c), buf1, buf2, c, c, c);
  94. #ifdef FEAT_MBYTE
  95.     c = c1;
  96.     c1 = c2;
  97.     c2 = 0;
  98. #endif
  99.     }
  100.  
  101. #ifdef FEAT_MBYTE
  102.     /* Repeat for combining characters. */
  103.     while (has_mbyte && (c >= 0x100 || (enc_utf8 && c >= 0x80)))
  104.     {
  105.     len = (int)STRLEN(IObuff);
  106.     /* This assumes every multi-byte char is printable... */
  107.     if (len > 0)
  108.         IObuff[len++] = ' ';
  109.     IObuff[len++] = '<';
  110.     if (utf_iscomposing(c)
  111. #ifdef USE_GUI
  112.         && !gui.in_use
  113. #endif
  114.         )
  115.         IObuff[len++] = ' '; /* draw composing char on top of a space */
  116.     IObuff[len + (*mb_char2bytes)(c, IObuff + len)] = NUL;
  117.     if (c < 0x10000)
  118.         sprintf((char *)IObuff + STRLEN(IObuff),
  119.                      "> %d, Hex %04x, Octal %o", c, c, c);
  120.     else
  121.         sprintf((char *)IObuff + STRLEN(IObuff),
  122.                      "> %d, Hex %08x, Octal %o", c, c, c);
  123.     c = c1;
  124.     c1 = c2;
  125.     c2 = 0;
  126.     }
  127. #endif
  128.  
  129.     msg(IObuff);
  130. }
  131.  
  132. #if defined(FEAT_EX_EXTRA) || defined(PROTO)
  133. /*
  134.  * ":left", ":center" and ":right": align text.
  135.  */
  136.     void
  137. ex_align(eap)
  138.     exarg_T    *eap;
  139. {
  140.     pos_T    save_curpos;
  141.     int        len;
  142.     int        indent = 0;
  143.     int        new_indent;
  144.     int        has_tab;
  145.     int        width;
  146.  
  147. #ifdef FEAT_RIGHTLEFT
  148.     if (curwin->w_p_rl)
  149.     {
  150.     /* switch left and right aligning */
  151.     if (eap->cmdidx == CMD_right)
  152.         eap->cmdidx = CMD_left;
  153.     else if (eap->cmdidx == CMD_left)
  154.         eap->cmdidx = CMD_right;
  155.     }
  156. #endif
  157.  
  158.     width = atoi((char *)eap->arg);
  159.     save_curpos = curwin->w_cursor;
  160.     if (eap->cmdidx == CMD_left)    /* width is used for new indent */
  161.     {
  162.     if (width >= 0)
  163.         indent = width;
  164.     }
  165.     else
  166.     {
  167.     /*
  168.      * if 'textwidth' set, use it
  169.      * else if 'wrapmargin' set, use it
  170.      * if invalid value, use 80
  171.      */
  172.     if (width <= 0)
  173.         width = curbuf->b_p_tw;
  174.     if (width == 0 && curbuf->b_p_wm > 0)
  175.         width = W_WIDTH(curwin) - curbuf->b_p_wm;
  176.     if (width <= 0)
  177.         width = 80;
  178.     }
  179.  
  180.     if (u_save((linenr_T)(eap->line1 - 1), (linenr_T)(eap->line2 + 1)) == FAIL)
  181.     return;
  182.  
  183.     for (curwin->w_cursor.lnum = eap->line1;
  184.          curwin->w_cursor.lnum <= eap->line2; ++curwin->w_cursor.lnum)
  185.     {
  186.     if (eap->cmdidx == CMD_left)        /* left align */
  187.         new_indent = indent;
  188.     else
  189.     {
  190.         len = linelen(eap->cmdidx == CMD_right ? &has_tab
  191.                            : NULL) - get_indent();
  192.  
  193.         if (len <= 0)            /* skip blank lines */
  194.         continue;
  195.  
  196.         if (eap->cmdidx == CMD_center)
  197.         new_indent = (width - len) / 2;
  198.         else
  199.         {
  200.         new_indent = width - len;    /* right align */
  201.  
  202.         /*
  203.          * Make sure that embedded TABs don't make the text go too far
  204.          * to the right.
  205.          */
  206.         if (has_tab)
  207.             while (new_indent > 0)
  208.             {
  209.             (void)set_indent(new_indent, 0);
  210.             if (linelen(NULL) <= width)
  211.             {
  212.                 /*
  213.                  * Now try to move the line as much as possible to
  214.                  * the right.  Stop when it moves too far.
  215.                  */
  216.                 do
  217.                 (void)set_indent(++new_indent, 0);
  218.                 while (linelen(NULL) <= width);
  219.                 --new_indent;
  220.                 break;
  221.             }
  222.             --new_indent;
  223.             }
  224.         }
  225.     }
  226.     if (new_indent < 0)
  227.         new_indent = 0;
  228.     (void)set_indent(new_indent, 0);        /* set indent */
  229.     }
  230.     changed_lines(eap->line1, 0, eap->line2 + 1, 0L);
  231.     curwin->w_cursor = save_curpos;
  232.     beginline(BL_WHITE | BL_FIX);
  233. }
  234.  
  235. /*
  236.  * Get the length of the current line, excluding trailing white space.
  237.  */
  238.     static int
  239. linelen(has_tab)
  240.     int        *has_tab;
  241. {
  242.     char_u  *line;
  243.     char_u  *first;
  244.     char_u  *last;
  245.     int        save;
  246.     int        len;
  247.  
  248.     /* find the first non-blank character */
  249.     line = ml_get_curline();
  250.     first = skipwhite(line);
  251.  
  252.     /* find the character after the last non-blank character */
  253.     for (last = first + STRLEN(first);
  254.                 last > first && vim_iswhite(last[-1]); --last)
  255.     ;
  256.     save = *last;
  257.     *last = NUL;
  258.     len = linetabsize(line);        /* get line length */
  259.     if (has_tab != NULL)        /* check for embedded TAB */
  260.     *has_tab = (vim_strrchr(first, TAB) != NULL);
  261.     *last = save;
  262.  
  263.     return len;
  264. }
  265.  
  266. /*
  267.  * ":retab".
  268.  */
  269.     void
  270. ex_retab(eap)
  271.     exarg_T    *eap;
  272. {
  273.     linenr_T    lnum;
  274.     int        got_tab = FALSE;
  275.     long    num_spaces = 0;
  276.     long    num_tabs;
  277.     long    len;
  278.     long    col;
  279.     long    vcol;
  280.     long    start_col = 0;        /* For start of white-space string */
  281.     long    start_vcol = 0;        /* For start of white-space string */
  282.     int        temp;
  283.     long    old_len;
  284.     char_u    *ptr;
  285.     char_u    *new_line = (char_u *)1;    /* init to non-NULL */
  286.     int        did_undo;        /* called u_save for current line */
  287.     int        new_ts;
  288.     int        save_list;
  289.     linenr_T    first_line = 0;        /* first changed line */
  290.     linenr_T    last_line = 0;        /* last changed line */
  291.  
  292.     save_list = curwin->w_p_list;
  293.     curwin->w_p_list = 0;        /* don't want list mode here */
  294.  
  295.     new_ts = getdigits(&(eap->arg));
  296.     if (new_ts == 0)
  297.     new_ts = curbuf->b_p_ts;
  298.     for (lnum = eap->line1; !got_int && lnum <= eap->line2; ++lnum)
  299.     {
  300.     ptr = ml_get(lnum);
  301.     col = 0;
  302.     vcol = 0;
  303.     did_undo = FALSE;
  304.     for (;;)
  305.     {
  306.         if (vim_iswhite(ptr[col]))
  307.         {
  308.         if (!got_tab && num_spaces == 0)
  309.         {
  310.             /* First consecutive white-space */
  311.             start_vcol = vcol;
  312.             start_col = col;
  313.         }
  314.         if (ptr[col] == ' ')
  315.             num_spaces++;
  316.         else
  317.             got_tab = TRUE;
  318.         }
  319.         else
  320.         {
  321.         if (got_tab || (eap->forceit && num_spaces > 1))
  322.         {
  323.             /* Retabulate this string of white-space */
  324.  
  325.             /* len is virtual length of white string */
  326.             len = num_spaces = vcol - start_vcol;
  327.             num_tabs = 0;
  328.             if (!curbuf->b_p_et)
  329.             {
  330.             temp = new_ts - (start_vcol % new_ts);
  331.             if (num_spaces >= temp)
  332.             {
  333.                 num_spaces -= temp;
  334.                 num_tabs++;
  335.             }
  336.             num_tabs += num_spaces / new_ts;
  337.             num_spaces -= (num_spaces / new_ts) * new_ts;
  338.             }
  339.             if (curbuf->b_p_et || got_tab ||
  340.                     (num_spaces + num_tabs < len))
  341.             {
  342.             if (did_undo == FALSE)
  343.             {
  344.                 did_undo = TRUE;
  345.                 if (u_save((linenr_T)(lnum - 1),
  346.                         (linenr_T)(lnum + 1)) == FAIL)
  347.                 {
  348.                 new_line = NULL;    /* flag out-of-memory */
  349.                 break;
  350.                 }
  351.             }
  352.  
  353.             /* len is actual number of white characters used */
  354.             len = num_spaces + num_tabs;
  355.             old_len = (long)STRLEN(ptr);
  356.             new_line = lalloc(old_len - col + start_col + len + 1,
  357.                                     TRUE);
  358.             if (new_line == NULL)
  359.                 break;
  360.             if (start_col > 0)
  361.                 mch_memmove(new_line, ptr, (size_t)start_col);
  362.             mch_memmove(new_line + start_col + len,
  363.                       ptr + col, (size_t)(old_len - col + 1));
  364.             ptr = new_line + start_col;
  365.             for (col = 0; col < len; col++)
  366.                 ptr[col] = (col < num_tabs) ? '\t' : ' ';
  367.             ml_replace(lnum, new_line, FALSE);
  368.             if (first_line == 0)
  369.                 first_line = lnum;
  370.             last_line = lnum;
  371.             ptr = new_line;
  372.             col = start_col + len;
  373.             }
  374.         }
  375.         got_tab = FALSE;
  376.         num_spaces = 0;
  377.         }
  378.         if (ptr[col] == NUL)
  379.         break;
  380.         vcol += chartabsize(ptr + col, (colnr_T)vcol);
  381. #ifdef FEAT_MBYTE
  382.         if (has_mbyte)
  383.         col += (*mb_ptr2len_check)(ptr + col);
  384.         else
  385. #endif
  386.         ++col;
  387.     }
  388.     if (new_line == NULL)            /* out of memory */
  389.         break;
  390.     line_breakcheck();
  391.     }
  392.     if (got_int)
  393.     EMSG(_(e_interr));
  394.  
  395.     if (curbuf->b_p_ts != new_ts)
  396.     redraw_curbuf_later(NOT_VALID);
  397.     if (first_line != 0)
  398.     changed_lines(first_line, 0, last_line + 1, 0L);
  399.  
  400.     curwin->w_p_list = save_list;    /* restore 'list' */
  401.  
  402.     curbuf->b_p_ts = new_ts;
  403.     coladvance(curwin->w_curswant);
  404.  
  405.     u_clearline();
  406. }
  407. #endif
  408.  
  409. /*
  410.  * :move command - move lines line1-line2 to line dest
  411.  *
  412.  * return FAIL for failure, OK otherwise
  413.  */
  414.     int
  415. do_move(line1, line2, dest)
  416.     linenr_T    line1;
  417.     linenr_T    line2;
  418.     linenr_T    dest;
  419. {
  420.     char_u    *str;
  421.     linenr_T    l;
  422.     linenr_T    extra;        /* Num lines added before line1 */
  423.     linenr_T    num_lines;  /* Num lines moved */
  424.     linenr_T    last_line;  /* Last line in file after adding new text */
  425.  
  426.     if (dest >= line1 && dest < line2)
  427.     {
  428.     EMSG(_("E134: Move lines into themselves"));
  429.     return FAIL;
  430.     }
  431.  
  432.     num_lines = line2 - line1 + 1;
  433.  
  434.     /*
  435.      * First we copy the old text to its new location -- webb
  436.      * Also copy the flag that ":global" command uses.
  437.      */
  438.     if (u_save(dest, dest + 1) == FAIL)
  439.     return FAIL;
  440.     for (extra = 0, l = line1; l <= line2; l++)
  441.     {
  442.     str = vim_strsave(ml_get(l + extra));
  443.     if (str != NULL)
  444.     {
  445.         ml_append(dest + l - line1, str, (colnr_T)0, FALSE);
  446.         vim_free(str);
  447.         if (dest < line1)
  448.         extra++;
  449.     }
  450.     }
  451.  
  452.     /*
  453.      * Now we must be careful adjusting our marks so that we don't overlap our
  454.      * mark_adjust() calls.
  455.      *
  456.      * We adjust the marks within the old text so that they refer to the
  457.      * last lines of the file (temporarily), because we know no other marks
  458.      * will be set there since these line numbers did not exist until we added
  459.      * our new lines.
  460.      *
  461.      * Then we adjust the marks on lines between the old and new text positions
  462.      * (either forwards or backwards).
  463.      *
  464.      * And Finally we adjust the marks we put at the end of the file back to
  465.      * their final destination at the new text position -- webb
  466.      */
  467.     last_line = curbuf->b_ml.ml_line_count;
  468.     mark_adjust(line1, line2, last_line - line2, 0L);
  469.     if (dest >= line2)
  470.     {
  471.     mark_adjust(line2 + 1, dest, -num_lines, 0L);
  472.     curbuf->b_op_start.lnum = dest - num_lines + 1;
  473.     curbuf->b_op_end.lnum = dest;
  474.     }
  475.     else
  476.     {
  477.     mark_adjust(dest + 1, line1 - 1, num_lines, 0L);
  478.     curbuf->b_op_start.lnum = dest + 1;
  479.     curbuf->b_op_end.lnum = dest + num_lines;
  480.     }
  481.     curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
  482.     mark_adjust(last_line - num_lines + 1, last_line,
  483.                          -(last_line - dest - extra), 0L);
  484.  
  485.     /*
  486.      * Now we delete the original text -- webb
  487.      */
  488.     if (u_save(line1 + extra - 1, line2 + extra + 1) == FAIL)
  489.     return FAIL;
  490.  
  491.     for (l = line1; l <= line2; l++)
  492.     ml_delete(line1 + extra, TRUE);
  493.  
  494.     if (!global_busy && num_lines > p_report)
  495.     {
  496.     if (num_lines == 1)
  497.         MSG(_("1 line moved"));
  498.     else
  499.         smsg((char_u *)_("%ld lines moved"), num_lines);
  500.     }
  501.  
  502.     /*
  503.      * Leave the cursor on the last of the moved lines.
  504.      */
  505.     if (dest >= line1)
  506.     curwin->w_cursor.lnum = dest;
  507.     else
  508.     curwin->w_cursor.lnum = dest + (line2 - line1) + 1;
  509.  
  510.     if (line1 < dest)
  511.     changed_lines(line1, 0, dest + num_lines + 1, 0L);
  512.     else
  513.     changed_lines(dest + 1, 0, line1 + num_lines, 0L);
  514.  
  515.     return OK;
  516. }
  517.  
  518. /*
  519.  * ":copy"
  520.  */
  521.     void
  522. ex_copy(line1, line2, n)
  523.     linenr_T    line1;
  524.     linenr_T    line2;
  525.     linenr_T    n;
  526. {
  527.     linenr_T    count;
  528.     char_u    *p;
  529.  
  530.     count = line2 - line1 + 1;
  531.     curbuf->b_op_start.lnum = n + 1;
  532.     curbuf->b_op_end.lnum = n + count;
  533.     curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
  534.  
  535.     /*
  536.      * there are three situations:
  537.      * 1. destination is above line1
  538.      * 2. destination is between line1 and line2
  539.      * 3. destination is below line2
  540.      *
  541.      * n = destination (when starting)
  542.      * curwin->w_cursor.lnum = destination (while copying)
  543.      * line1 = start of source (while copying)
  544.      * line2 = end of source (while copying)
  545.      */
  546.     if (u_save(n, n + 1) == FAIL)
  547.     return;
  548.  
  549.     curwin->w_cursor.lnum = n;
  550.     while (line1 <= line2)
  551.     {
  552.     /* need to use vim_strsave() because the line will be unlocked within
  553.      * ml_append() */
  554.     p = vim_strsave(ml_get(line1));
  555.     if (p != NULL)
  556.     {
  557.         ml_append(curwin->w_cursor.lnum, p, (colnr_T)0, FALSE);
  558.         vim_free(p);
  559.     }
  560.     /* situation 2: skip already copied lines */
  561.     if (line1 == n)
  562.         line1 = curwin->w_cursor.lnum;
  563.     ++line1;
  564.     if (curwin->w_cursor.lnum < line1)
  565.         ++line1;
  566.     if (curwin->w_cursor.lnum < line2)
  567.         ++line2;
  568.     ++curwin->w_cursor.lnum;
  569.     }
  570.  
  571.     appended_lines_mark(n, count);
  572.  
  573.     msgmore((long)count);
  574. }
  575.  
  576. /*
  577.  * Handle the ":!cmd" command.    Also for ":r !cmd" and ":w !cmd"
  578.  * Bangs in the argument are replaced with the previously entered command.
  579.  * Remember the argument.
  580.  *
  581.  * RISCOS: Bangs only replaced when followed by a space, since many
  582.  * pathnames contain one.
  583.  */
  584.     void
  585. do_bang(addr_count, eap, forceit, do_in, do_out)
  586.     int        addr_count;
  587.     exarg_T    *eap;
  588.     int        forceit;
  589.     int        do_in, do_out;
  590. {
  591.     char_u        *arg = eap->arg;    /* command */
  592.     linenr_T        line1 = eap->line1;    /* start of range */
  593.     linenr_T        line2 = eap->line2;    /* end of range */
  594.     static char_u    *prevcmd = NULL;    /* the previous command */
  595.     char_u        *newcmd = NULL;        /* the new command */
  596.     int            free_newcmd = FALSE;    /* need to free() newcmd */
  597.     int            ins_prevcmd;
  598.     char_u        *t;
  599.     char_u        *p;
  600.     char_u        *trailarg;
  601.     int            len;
  602.     int            scroll_save = msg_scroll;
  603.  
  604.     /*
  605.      * Disallow shell commands for "rvim".
  606.      * Disallow shell commands from .exrc and .vimrc in current directory for
  607.      * security reasons.
  608.      */
  609.     if (check_restricted() || check_secure())
  610.     return;
  611.  
  612.     if (addr_count == 0)        /* :! */
  613.     {
  614.     msg_scroll = FALSE;        /* don't scroll here */
  615.     autowrite_all();
  616.     msg_scroll = scroll_save;
  617.     }
  618.  
  619.     /*
  620.      * Try to find an embedded bang, like in :!<cmd> ! [args]
  621.      * (:!! is indicated by the 'forceit' variable)
  622.      */
  623.     ins_prevcmd = forceit;
  624.     trailarg = arg;
  625.     do
  626.     {
  627.     len = (int)STRLEN(trailarg) + 1;
  628.     if (newcmd != NULL)
  629.         len += (int)STRLEN(newcmd);
  630.     if (ins_prevcmd)
  631.     {
  632.         if (prevcmd == NULL)
  633.         {
  634.         EMSG(_(e_noprev));
  635.         vim_free(newcmd);
  636.         return;
  637.         }
  638.         len += (int)STRLEN(prevcmd);
  639.     }
  640.     if ((t = alloc(len)) == NULL)
  641.     {
  642.         vim_free(newcmd);
  643.         return;
  644.     }
  645.     *t = NUL;
  646.     if (newcmd != NULL)
  647.         STRCAT(t, newcmd);
  648.     if (ins_prevcmd)
  649.         STRCAT(t, prevcmd);
  650.     p = t + STRLEN(t);
  651.     STRCAT(t, trailarg);
  652.     vim_free(newcmd);
  653.     newcmd = t;
  654.  
  655.     /*
  656.      * Scan the rest of the argument for '!', which is replaced by the
  657.      * previous command.  "\!" is replaced by "!" (this is vi compatible).
  658.      */
  659.     trailarg = NULL;
  660.     while (*p)
  661.     {
  662.         if (*p == '!'
  663. #ifdef RISCOS
  664.             && (p[1] == ' ' || p[1] == NUL)
  665. #endif
  666.                     )
  667.         {
  668.         if (p > newcmd && p[-1] == '\\')
  669.             mch_memmove(p - 1, p, (size_t)(STRLEN(p) + 1));
  670.         else
  671.         {
  672.             trailarg = p;
  673.             *trailarg++ = NUL;
  674.             ins_prevcmd = TRUE;
  675.             break;
  676.         }
  677.         }
  678.         ++p;
  679.     }
  680.     } while (trailarg != NULL);
  681.  
  682.     vim_free(prevcmd);
  683.     prevcmd = newcmd;
  684.  
  685.     if (bangredo)        /* put cmd in redo buffer for ! command */
  686.     {
  687.     AppendToRedobuffLit(prevcmd);
  688.     AppendToRedobuff((char_u *)"\n");
  689.     bangredo = FALSE;
  690.     }
  691.     /*
  692.      * Add quotes around the command, for shells that need them.
  693.      */
  694.     if (*p_shq != NUL)
  695.     {
  696.     newcmd = alloc((unsigned)(STRLEN(prevcmd) + 2 * STRLEN(p_shq) + 1));
  697.     if (newcmd == NULL)
  698.         return;
  699.     STRCPY(newcmd, p_shq);
  700.     STRCAT(newcmd, prevcmd);
  701.     STRCAT(newcmd, p_shq);
  702.     free_newcmd = TRUE;
  703.     }
  704.     if (addr_count == 0)        /* :! */
  705.     {
  706.     /* echo the command */
  707.     msg_start();
  708.     msg_putchar(':');
  709.     msg_putchar('!');
  710.     msg_outtrans(newcmd);
  711.     msg_clr_eos();
  712.     windgoto(msg_row, msg_col);
  713.  
  714.     do_shell(newcmd, 0);
  715.     }
  716.     else                /* :range! */
  717.     /* Careful: This may recursively call do_bang() again! (because of
  718.      * autocommands) */
  719.     do_filter(line1, line2, eap, newcmd, do_in, do_out);
  720.     if (free_newcmd)
  721.     vim_free(newcmd);
  722. }
  723.  
  724. /*
  725.  * do_filter: filter lines through a command given by the user
  726.  *
  727.  * We use temp files and the call_shell() routine here. This would normally
  728.  * be done using pipes on a UNIX machine, but this is more portable to
  729.  * non-unix machines. The call_shell() routine needs to be able
  730.  * to deal with redirection somehow, and should handle things like looking
  731.  * at the PATH env. variable, and adding reasonable extensions to the
  732.  * command name given by the user. All reasonable versions of call_shell()
  733.  * do this.
  734.  * We use input redirection if do_in is TRUE.
  735.  * We use output redirection if do_out is TRUE.
  736.  */
  737.     static void
  738. do_filter(line1, line2, eap, cmd, do_in, do_out)
  739.     linenr_T    line1, line2;
  740.     exarg_T    *eap;        /* for forced 'ff' and 'fenc' */
  741.     char_u    *cmd;
  742.     int        do_in, do_out;
  743. {
  744.     char_u    *itmp = NULL;
  745.     char_u    *otmp = NULL;
  746.     linenr_T    linecount;
  747.     pos_T    cursor_save;
  748.     char_u    *cmd_buf;
  749. #ifdef FEAT_AUTOCMD
  750.     buf_T    *old_curbuf = curbuf;
  751. #endif
  752.  
  753.     if (*cmd == NUL)        /* no filter command */
  754.     return;
  755.  
  756. #ifdef WIN3264
  757.     /*
  758.      * Check if external commands are allowed now.
  759.      */
  760.     if (can_end_termcap_mode(TRUE) == FALSE)
  761.     return;
  762. #endif
  763.  
  764.     cursor_save = curwin->w_cursor;
  765.     linecount = line2 - line1 + 1;
  766.     curwin->w_cursor.lnum = line1;
  767.     curwin->w_cursor.col = 0;
  768.     changed_line_abv_curs();
  769.     invalidate_botline();
  770.  
  771.     /*
  772.      * 1. Form temp file names
  773.      * 2. Write the lines to a temp file
  774.      * 3. Run the filter command on the temp file
  775.      * 4. Read the output of the command into the buffer
  776.      * 5. Delete the original lines to be filtered
  777.      * 6. Remove the temp files
  778.      */
  779.  
  780.     if ((do_in && (itmp = vim_tempname('i')) == NULL)
  781.         || (do_out && (otmp = vim_tempname('o')) == NULL))
  782.     {
  783.     EMSG(_(e_notmp));
  784.     goto filterend;
  785.     }
  786.  
  787. /*
  788.  * The writing and reading of temp files will not be shown.
  789.  * Vi also doesn't do this and the messages are not very informative.
  790.  */
  791.     ++no_wait_return;        /* don't call wait_return() while busy */
  792.     if (do_in && buf_write(curbuf, itmp, NULL, line1, line2, eap,
  793.                        FALSE, FALSE, FALSE, TRUE) == FAIL)
  794.     {
  795.     msg_putchar('\n');        /* keep message from buf_write() */
  796.     --no_wait_return;
  797.     (void)EMSG2(_(e_notcreate), itmp);    /* will call wait_return */
  798.     goto filterend;
  799.     }
  800. #ifdef FEAT_AUTOCMD
  801.     if (curbuf != old_curbuf)
  802.     goto filterend;
  803. #endif
  804.  
  805.     if (!do_out)
  806.     msg_putchar('\n');
  807.  
  808.     cmd_buf = make_filter_cmd(cmd, itmp, otmp);
  809.     if (cmd_buf == NULL)
  810.     goto filterend;
  811.  
  812.     windgoto((int)Rows - 1, 0);
  813.     cursor_on();
  814.  
  815.     /*
  816.      * When not redirecting the output the command can write anything to the
  817.      * screen. If 'shellredir' is equal to ">", screen may be messed up by
  818.      * stderr output of external command. Clear the screen later.
  819.      * If do_in is FALSE, this could be something like ":r !cat", which may
  820.      * also mess up the screen, clear it later.
  821.      */
  822.     if (!do_out || STRCMP(p_srr, ">") == 0 || !do_in)
  823.     redraw_later_clear();
  824.  
  825.     /*
  826.      * When call_shell() fails wait_return() is called to give the user a
  827.      * chance to read the error messages. Otherwise errors are ignored, so you
  828.      * can see the error messages from the command that appear on stdout; use
  829.      * 'u' to fix the text
  830.      * Switch to cooked mode when not redirecting stdin, avoids that something
  831.      * like ":r !cat" hangs.
  832.      * Pass on the SHELL_DOOUT flag when the output is being redirected.
  833.      */
  834.     if (call_shell(cmd_buf, SHELL_FILTER | SHELL_COOKED
  835.                         | (do_out ? SHELL_DOOUT : 0)))
  836.     {
  837.     redraw_later_clear();
  838.     wait_return(FALSE);
  839.     }
  840.     vim_free(cmd_buf);
  841.  
  842.     did_check_timestamps = FALSE;
  843.     need_check_timestamps = TRUE;
  844.  
  845.     if (do_out)
  846.     {
  847.     if (u_save((linenr_T)(line2), (linenr_T)(line2 + 1)) == FAIL)
  848.         goto error;
  849.     redraw_curbuf_later(VALID);
  850.     if (readfile(otmp, NULL, line2, (linenr_T)0, (linenr_T)MAXLNUM, eap,
  851.                              READ_FILTER) == FAIL)
  852.     {
  853.         msg_putchar('\n');
  854.         EMSG2(_(e_notread), otmp);
  855.         goto error;
  856.     }
  857. #ifdef FEAT_AUTOCMD
  858.     if (curbuf != old_curbuf)
  859.         goto filterend;
  860. #endif
  861.  
  862.     if (do_in)
  863.     {
  864.         /*
  865.          * Put cursor on first filtered line for ":range!cmd".
  866.          * Adjust '[ and '] (set by buf_write()).
  867.          */
  868.         curwin->w_cursor.lnum = line1;
  869.         del_lines(linecount, TRUE);
  870.         curbuf->b_op_start.lnum -= linecount;    /* adjust '[ */
  871.         curbuf->b_op_end.lnum -= linecount;        /* adjust '] */
  872.         write_lnum_adjust(-linecount);        /* adjust last line
  873.                                for next write */
  874.     }
  875.     else
  876.     {
  877.         /*
  878.          * Put cursor on last new line for ":r !cmd".
  879.          */
  880.         curwin->w_cursor.lnum = curbuf->b_op_end.lnum;
  881.         linecount = curbuf->b_op_end.lnum - curbuf->b_op_start.lnum + 1;
  882.     }
  883.     beginline(BL_WHITE | BL_FIX);        /* cursor on first non-blank */
  884.     --no_wait_return;
  885.  
  886.     if (linecount > p_report)
  887.     {
  888.         if (do_in)
  889.         {
  890.         sprintf((char *)msg_buf, _("%ld lines filtered"),
  891.                                  (long)linecount);
  892.         if (msg(msg_buf) && !msg_scroll)
  893.         {
  894.             /* save message to display it after redraw */
  895.             set_keep_msg(msg_buf);
  896.             keep_msg_attr = 0;
  897.         }
  898.         }
  899.         else
  900.         msgmore((long)linecount);
  901.     }
  902.     }
  903.     else
  904.     {
  905. error:
  906.     /* put cursor back in same position for ":w !cmd" */
  907.     curwin->w_cursor = cursor_save;
  908.     --no_wait_return;
  909.     wait_return(FALSE);
  910.     }
  911.  
  912. filterend:
  913.  
  914. #ifdef FEAT_AUTOCMD
  915.     if (curbuf != old_curbuf)
  916.     {
  917.     --no_wait_return;
  918.     EMSG(_("E135: *Filter* Autocommands must not change current buffer"));
  919.     }
  920. #endif
  921.     if (itmp != NULL)
  922.     mch_remove(itmp);
  923.     if (otmp != NULL)
  924.     mch_remove(otmp);
  925.     vim_free(itmp);
  926.     vim_free(otmp);
  927. }
  928.  
  929. /*
  930.  * Call a shell to execute a command.
  931.  * When "cmd" is NULL start an interactive shell.
  932.  */
  933.     void
  934. do_shell(cmd, flags)
  935.     char_u    *cmd;
  936.     int        flags;    /* may be SHELL_DOOUT when output is redirected */
  937. {
  938.     buf_T    *buf;
  939. #ifndef FEAT_GUI_MSWIN
  940.     int        save_nwr;
  941. #endif
  942. #ifdef MSWIN
  943.     int        winstart = FALSE;
  944. #endif
  945.  
  946.     /*
  947.      * Disallow shell commands for "rvim".
  948.      * Disallow shell commands from .exrc and .vimrc in current directory for
  949.      * security reasons.
  950.      */
  951.     if (check_restricted() || check_secure())
  952.     {
  953.     msg_end();
  954.     return;
  955.     }
  956.  
  957. #ifdef MSWIN
  958.     /*
  959.      * Check if external commands are allowed now.
  960.      */
  961.     if (can_end_termcap_mode(TRUE) == FALSE)
  962.     return;
  963.  
  964.     /*
  965.      * Check if ":!start" is used.
  966.      */
  967.     if (cmd != NULL)
  968.     winstart = (STRNICMP(cmd, "start ", 6) == 0);
  969. #endif
  970.  
  971.     /*
  972.      * For autocommands we want to get the output on the current screen, to
  973.      * avoid having to type return below.
  974.      */
  975.     msg_putchar('\r');            /* put cursor at start of line */
  976. #ifdef FEAT_AUTOCMD
  977.     if (!autocmd_busy)
  978. #endif
  979.     {
  980. #ifdef MSWIN
  981.     if (!winstart)
  982. #endif
  983.         stoptermcap();
  984.     }
  985. #ifdef MSWIN
  986.     if (!winstart)
  987. #endif
  988.     msg_putchar('\n');        /* may shift screen one line up */
  989.  
  990.     /* warning message before calling the shell */
  991.     if (p_warn
  992. #ifdef FEAT_AUTOCMD
  993.         && !autocmd_busy
  994. #endif
  995.         && msg_silent == 0)
  996.     for (buf = firstbuf; buf; buf = buf->b_next)
  997.         if (bufIsChanged(buf))
  998.         {
  999. #ifdef FEAT_GUI_MSWIN
  1000.         if (!winstart)
  1001.             starttermcap();    /* don't want a message box here */
  1002. #endif
  1003.         MSG_PUTS(_("[No write since last change]\n"));
  1004. #ifdef FEAT_GUI_MSWIN
  1005.         if (!winstart)
  1006.             stoptermcap();
  1007. #endif
  1008.         break;
  1009.         }
  1010.  
  1011.     /* This windgoto is required for when the '\n' resulted in a "delete line
  1012.      * 1" command to the terminal. */
  1013.     if (!swapping_screen())
  1014.     windgoto(msg_row, msg_col);
  1015.     cursor_on();
  1016.     (void)call_shell(cmd, SHELL_COOKED | flags);
  1017.     did_check_timestamps = FALSE;
  1018.     need_check_timestamps = TRUE;
  1019.  
  1020.     /*
  1021.      * put the message cursor at the end of the screen, avoids wait_return()
  1022.      * to overwrite the text that the external command showed
  1023.      */
  1024.     if (!swapping_screen())
  1025.     {
  1026.     msg_row = Rows - 1;
  1027.     msg_col = 0;
  1028.     }
  1029.  
  1030. #ifdef FEAT_AUTOCMD
  1031.     if (autocmd_busy)
  1032.     {
  1033.     if (msg_silent == 0)
  1034.         redraw_later_clear();
  1035.     }
  1036.     else
  1037. #endif
  1038.     {
  1039.     /*
  1040.      * For ":sh" there is no need to call wait_return(), just redraw.
  1041.      * Also for the Win32 GUI (the output is in a console window).
  1042.      * Otherwise there is probably text on the screen that the user wants
  1043.      * to read before redrawing, so call wait_return().
  1044.      */
  1045. #ifndef FEAT_GUI_MSWIN
  1046.     if (cmd == NULL
  1047. # ifdef WIN3264
  1048.         || (winstart && !need_wait_return)
  1049. # endif
  1050.        )
  1051.     {
  1052.         if (msg_silent == 0)
  1053.         redraw_later_clear();
  1054.         need_wait_return = FALSE;
  1055.     }
  1056.     else
  1057.     {
  1058.         /*
  1059.          * If we switch screens when starttermcap() is called, we really
  1060.          * want to wait for "hit return to continue".
  1061.          */
  1062.         save_nwr = no_wait_return;
  1063.         if (swapping_screen())
  1064.         no_wait_return = FALSE;
  1065. # ifdef AMIGA
  1066.         wait_return(term_console ? -1 : msg_silent == 0);    /* see below */
  1067. # else
  1068.         wait_return(msg_silent == 0);
  1069. # endif
  1070.         no_wait_return = save_nwr;
  1071.     }
  1072. #endif /* FEAT_GUI_W32 */
  1073.  
  1074. #ifdef MSWIN
  1075.     if (!winstart) /* if winstart==TRUE, never stopped termcap! */
  1076. #endif
  1077.         starttermcap();    /* start termcap if not done by wait_return() */
  1078.  
  1079.     /*
  1080.      * In an Amiga window redrawing is caused by asking the window size.
  1081.      * If we got an interrupt this will not work. The chance that the
  1082.      * window size is wrong is very small, but we need to redraw the
  1083.      * screen.  Don't do this if ':' hit in wait_return().    THIS IS UGLY
  1084.      * but it saves an extra redraw.
  1085.      */
  1086. #ifdef AMIGA
  1087.     if (skip_redraw)        /* ':' hit in wait_return() */
  1088.     {
  1089.         if (msg_silent == 0)
  1090.         redraw_later_clear();
  1091.     }
  1092.     else if (term_console)
  1093.     {
  1094.         OUT_STR(IF_EB("\033[0 q", ESC_STR "[0 q"));    /* get window size */
  1095.         if (got_int && msg_silent == 0)
  1096.         redraw_later_clear();    /* if got_int is TRUE, redraw needed */
  1097.         else
  1098.         must_redraw = 0;    /* no extra redraw needed */
  1099.     }
  1100. #endif
  1101.     }
  1102.  
  1103.     /* display any error messages now */
  1104.     display_errors();
  1105. }
  1106.  
  1107. /*
  1108.  * Create a shell command from a command string, input redirection file and
  1109.  * output redirection file.
  1110.  * Returns an allocated string with the shell command, or NULL for failure.
  1111.  */
  1112.     char_u *
  1113. make_filter_cmd(cmd, itmp, otmp)
  1114.     char_u    *cmd;        /* command */
  1115.     char_u    *itmp;        /* NULL or name of input file */
  1116.     char_u    *otmp;        /* NULL or name of output file */
  1117. {
  1118.     char_u    *buf;
  1119.     long_u    len;
  1120.  
  1121.     len = (long_u)STRLEN(cmd) + 3;            /* "()" + NUL */
  1122.     if (itmp != NULL)
  1123.     len += (long_u)STRLEN(itmp) + 9;        /* " { < " + " } " */
  1124.     if (otmp != NULL)
  1125.     len += (long_u)STRLEN(otmp) + (long_u)STRLEN(p_srr) + 2; /* "  " */
  1126.     buf = lalloc(len, TRUE);
  1127.     if (buf == NULL)
  1128.     return NULL;
  1129.  
  1130. #if (defined(UNIX) && !defined(ARCHIE)) || defined(OS2)
  1131.     /*
  1132.      * put braces around the command (for concatenated commands)
  1133.      */
  1134.     sprintf((char *)buf, "(%s)", (char *)cmd);
  1135.     if (itmp != NULL)
  1136.     {
  1137.     STRCAT(buf, " < ");
  1138.     STRCAT(buf, itmp);
  1139.     }
  1140. #else
  1141.     /*
  1142.      * for shells that don't understand braces around commands, at least allow
  1143.      * the use of commands in a pipe.
  1144.      */
  1145.     STRCPY(buf, cmd);
  1146.     if (itmp != NULL)
  1147.     {
  1148.     char_u    *p;
  1149.  
  1150.     /*
  1151.      * If there is a pipe, we have to put the '<' in front of it.
  1152.      * Don't do this when 'shellquote' is not empty, otherwise the
  1153.      * redirection would be inside the quotes.
  1154.      */
  1155.     if (*p_shq == NUL)
  1156.     {
  1157.         p = vim_strchr(buf, '|');
  1158.         if (p != NULL)
  1159.         *p = NUL;
  1160.     }
  1161. # ifdef RISCOS
  1162.     STRCAT(buf, " { < ");    /* Use RISC OS notation for input. */
  1163.     STRCAT(buf, itmp);
  1164.     STRCAT(buf, " } ");
  1165. # else
  1166.     STRCAT(buf, " <");    /* " < " causes problems on Amiga */
  1167.     STRCAT(buf, itmp);
  1168. # endif
  1169.     if (*p_shq == NUL)
  1170.     {
  1171.         p = vim_strchr(cmd, '|');
  1172.         if (p != NULL)
  1173.         {
  1174.         STRCAT(buf, " ");   /* insert a space before the '|' for DOS */
  1175.         STRCAT(buf, p);
  1176.         }
  1177.     }
  1178.     }
  1179. #endif
  1180.     if (otmp != NULL)
  1181.     append_redir(buf, p_srr, otmp);
  1182.  
  1183.     return buf;
  1184. }
  1185.  
  1186. /*
  1187.  * Append output redirection for file "fname" to the end of string buffer "buf"
  1188.  * Works with the 'shellredir' and 'shellpipe' options.
  1189.  * The caller should make sure that there is enough room:
  1190.  *    STRLEN(opt) + STRLEN(fname) + 3
  1191.  */
  1192.     void
  1193. append_redir(buf, opt, fname)
  1194.     char_u    *buf;
  1195.     char_u    *opt;
  1196.     char_u    *fname;
  1197. {
  1198.     char_u    *p;
  1199.  
  1200.     buf += STRLEN(buf);
  1201.     /* find "%s", skipping "%%" */
  1202.     for (p = opt; (p = vim_strchr(p, '%')) != NULL; ++p)
  1203.     if (p[1] == 's')
  1204.         break;
  1205.     if (p != NULL)
  1206.     {
  1207.     *buf = ' '; /* not really needed? Not with sh, ksh or bash */
  1208.     sprintf((char *)buf + 1, (char *)opt, (char *)fname);
  1209.     }
  1210.     else
  1211.     sprintf((char *)buf,
  1212. #ifdef FEAT_QUICKFIX
  1213. # ifndef RISCOS
  1214.         opt != p_sp ? " %s%s" :
  1215. # endif
  1216.         " %s %s",
  1217. #else
  1218. # ifndef RISCOS
  1219.         " %s%s",    /* " > %s" causes problems on Amiga */
  1220. # else
  1221.         " %s %s",    /* But is needed for 'shellpipe' and RISC OS */
  1222. # endif
  1223. #endif
  1224.         (char *)opt, (char *)fname);
  1225. }
  1226.  
  1227. #ifdef FEAT_VIMINFO
  1228.  
  1229. static int no_viminfo __ARGS((void));
  1230. static int  viminfo_errcnt;
  1231.  
  1232.     static int
  1233. no_viminfo()
  1234. {
  1235.     /* "vim -i NONE" does not read or write a viminfo file */
  1236.     return (use_viminfo != NULL && STRCMP(use_viminfo, "NONE") == 0);
  1237. }
  1238.  
  1239. /*
  1240.  * Report an error for reading a viminfo file.
  1241.  * Count the number of errors.    When there are more than 10, return TRUE.
  1242.  */
  1243.     int
  1244. viminfo_error(message, line)
  1245.     char    *message;
  1246.     char_u  *line;
  1247. {
  1248.     sprintf((char *)IObuff, _("viminfo: %s in line: "), message);
  1249.     STRNCAT(IObuff, line, IOSIZE - STRLEN(IObuff));
  1250.     emsg(IObuff);
  1251.     if (++viminfo_errcnt >= 10)
  1252.     {
  1253.     EMSG(_("E136: viminfo: Too many errors, skipping rest of file"));
  1254.     return TRUE;
  1255.     }
  1256.     return FALSE;
  1257. }
  1258.  
  1259. /*
  1260.  * read_viminfo() -- Read the viminfo file.  Registers etc. which are already
  1261.  * set are not over-written unless force is TRUE. -- webb
  1262.  */
  1263.     int
  1264. read_viminfo(file, want_info, want_marks, forceit)
  1265.     char_u    *file;
  1266.     int        want_info;
  1267.     int        want_marks;
  1268.     int        forceit;
  1269. {
  1270.     FILE    *fp;
  1271.     char_u    *fname;
  1272.  
  1273.     if (no_viminfo())
  1274.     return FAIL;
  1275.  
  1276.     fname = viminfo_filename(file);        /* may set to default if NULL */
  1277.     if (fname == NULL)
  1278.     return FAIL;
  1279.     fp = mch_fopen((char *)fname, READBIN);
  1280.  
  1281.     if (p_verbose > 0)
  1282.     smsg((char_u *)_("Reading viminfo file \"%s\"%s%s%s"), fname,
  1283.             want_info ? _(" info") : "",
  1284.             want_marks ? _(" marks") : "",
  1285.             fp == NULL ? _(" FAILED") : "");
  1286.  
  1287.     vim_free(fname);
  1288.     if (fp == NULL)
  1289.     return FAIL;
  1290.  
  1291.     viminfo_errcnt = 0;
  1292.     do_viminfo(fp, NULL, want_info, want_marks, forceit);
  1293.  
  1294.     fclose(fp);
  1295.  
  1296.     return OK;
  1297. }
  1298.  
  1299. /*
  1300.  * write_viminfo() -- Write the viminfo file.  The old one is read in first so
  1301.  * that effectively a merge of current info and old info is done.  This allows
  1302.  * multiple vims to run simultaneously, without losing any marks etc.  If
  1303.  * forceit is TRUE, then the old file is not read in, and only internal info is
  1304.  * written to the file. -- webb
  1305.  */
  1306.     void
  1307. write_viminfo(file, forceit)
  1308.     char_u    *file;
  1309.     int        forceit;
  1310. {
  1311.     char_u    *fname;
  1312.     FILE    *fp_in = NULL;    /* input viminfo file, if any */
  1313.     FILE    *fp_out = NULL;    /* output viminfo file */
  1314.     char_u    *tempname = NULL;    /* name of temp viminfo file */
  1315.     struct stat    st_new;        /* mch_stat() of potential new file */
  1316.     char_u    *wp;
  1317. #if defined(UNIX) || defined(VMS)
  1318.     mode_t    umask_save;
  1319. #endif
  1320. #ifdef UNIX
  1321.     int        shortname = FALSE;    /* use 8.3 file name */
  1322.     struct stat    st_old;        /* mch_stat() of existing viminfo file */
  1323. #endif
  1324.  
  1325.     if (no_viminfo())
  1326.     return;
  1327.  
  1328.     fname = viminfo_filename(file);    /* may set to default if NULL */
  1329.     if (fname == NULL)
  1330.     return;
  1331.  
  1332.     fp_in = mch_fopen((char *)fname, READBIN);
  1333.     if (fp_in == NULL)
  1334.     {
  1335.     /* if it does exist, but we can't read it, don't try writing */
  1336.     if (mch_stat((char *)fname, &st_new) == 0)
  1337.         goto end;
  1338. #if defined(UNIX) || defined(VMS)
  1339.     /*
  1340.      * For Unix we create the .viminfo non-accessible for others,
  1341.      * because it may contain text from non-accessible documents.
  1342.      */
  1343.     umask_save = umask(077);
  1344. #endif
  1345.     fp_out = mch_fopen((char *)fname, WRITEBIN);
  1346. #if defined(UNIX) || defined(VMS)
  1347.     (void)umask(umask_save);
  1348. #endif
  1349.     }
  1350.     else
  1351.     {
  1352.     /*
  1353.      * There is an existing viminfo file.  Create a temporary file to
  1354.      * write the new viminfo into, in the same directory as the
  1355.      * existing viminfo file, which will be renamed later.
  1356.      */
  1357. #ifdef UNIX
  1358.     /*
  1359.      * For Unix we check the owner of the file.  It's not very nice to
  1360.      * overwrite a user's viminfo file after a "su root", with a
  1361.      * viminfo file that the user can't read.
  1362.      */
  1363.     st_old.st_dev = st_old.st_ino = 0;
  1364.     st_old.st_mode = 0600;
  1365.     if (mch_stat((char *)fname, &st_old) == 0 && getuid() &&
  1366.         !(st_old.st_uid == getuid()
  1367.             ? (st_old.st_mode & 0200)
  1368.             : (st_old.st_gid == getgid()
  1369.                 ? (st_old.st_mode & 0020)
  1370.                 : (st_old.st_mode & 0002))))
  1371.     {
  1372.         int    tt;
  1373.  
  1374.         /* avoid a wait_return for this message, it's annoying */
  1375.         tt = msg_didany;
  1376.         EMSG2(_("E137: Viminfo file is not writable: %s"), fname);
  1377.         msg_didany = tt;
  1378.         goto end;
  1379.     }
  1380. #endif
  1381.  
  1382.     /*
  1383.      * Make tempname.
  1384.      * May try twice: Once normal and once with shortname set, just in
  1385.      * case somebody puts his viminfo file in an 8.3 filesystem.
  1386.      */
  1387.     for (;;)
  1388.     {
  1389.         tempname = buf_modname(
  1390. #ifdef UNIX
  1391.                     shortname,
  1392. #else
  1393. # ifdef SHORT_FNAME
  1394.                     TRUE,
  1395. # else
  1396. #  ifdef FEAT_GUI_W32
  1397.                     gui_is_win32s(),
  1398. #  else
  1399.                     FALSE,
  1400. #  endif
  1401. # endif
  1402. #endif
  1403.                     fname,
  1404. #ifdef VMS
  1405.                     (char_u *)"-tmp",
  1406. #else
  1407. # ifdef RISCOS
  1408.                     (char_u *)"/tmp",
  1409. # else
  1410.                     (char_u *)".tmp",
  1411. # endif
  1412. #endif
  1413.                     FALSE);
  1414.         if (tempname == NULL)        /* out of memory */
  1415.         break;
  1416.  
  1417.         /*
  1418.          * Check if tempfile already exists.  Never overwrite an
  1419.          * existing file!
  1420.          */
  1421.         if (mch_stat((char *)tempname, &st_new) == 0)
  1422.         {
  1423. #ifdef UNIX
  1424.         /*
  1425.          * Check if tempfile is same as original file.  May happen
  1426.          * when modname() gave the same file back.  E.g.  silly
  1427.          * link, or file name-length reached.  Try again with
  1428.          * shortname set.
  1429.          */
  1430.         if (!shortname && st_new.st_dev == st_old.st_dev &&
  1431.             st_new.st_ino == st_old.st_ino)
  1432.         {
  1433.             vim_free(tempname);
  1434.             tempname = NULL;
  1435.             shortname = TRUE;
  1436.             continue;
  1437.         }
  1438. #endif
  1439.         /*
  1440.          * Try another name.  Change one character, just before
  1441.          * the extension.  This should also work for an 8.3
  1442.          * file name, when after adding the extension it still is
  1443.          * the same file as the original.
  1444.          */
  1445.         wp = tempname + STRLEN(tempname) - 5;
  1446.         if (wp < gettail(tempname))        /* empty file name? */
  1447.             wp = gettail(tempname);
  1448.         for (*wp = 'z'; mch_stat((char *)tempname, &st_new) == 0;
  1449.                                     --*wp)
  1450.         {
  1451.             /*
  1452.              * They all exist?  Must be something wrong! Don't
  1453.              * write the viminfo file then.
  1454.              */
  1455.             if (*wp == 'a')
  1456.             {
  1457.             vim_free(tempname);
  1458.             tempname = NULL;
  1459.             break;
  1460.             }
  1461.         }
  1462.         }
  1463.         break;
  1464.     }
  1465.  
  1466.     if (tempname != NULL)
  1467.     {
  1468.         fp_out = mch_fopen((char *)tempname, WRITEBIN);
  1469.  
  1470.         /*
  1471.          * If we can't create in the same directory, try creating a
  1472.          * "normal" temp file.
  1473.          */
  1474.         if (fp_out == NULL)
  1475.         {
  1476.         vim_free(tempname);
  1477.         if ((tempname = vim_tempname('o')) != NULL)
  1478.             fp_out = mch_fopen((char *)tempname, WRITEBIN);
  1479.         }
  1480. #ifdef UNIX
  1481.         /*
  1482.          * Set file protection same as original file, but strip s-bit
  1483.          * and make sure the owner can read/write it.
  1484.          */
  1485.         if (fp_out != NULL)
  1486.         {
  1487.         (void)mch_setperm(tempname,
  1488.                   (long)((st_old.st_mode & 0777) | 0600));
  1489.         /* this only works for root: */
  1490.         (void)chown((char *)tempname, st_old.st_uid, st_old.st_gid);
  1491.         }
  1492. #endif
  1493.     }
  1494.     }
  1495.  
  1496.     /*
  1497.      * Check if the new viminfo file can be written to.
  1498.      */
  1499.     if (fp_out == NULL)
  1500.     {
  1501.     EMSG2(_("E138: Can't write viminfo file %s!"),
  1502.                         fp_in == NULL ? fname : tempname);
  1503.     if (fp_in != NULL)
  1504.         fclose(fp_in);
  1505.     goto end;
  1506.     }
  1507.  
  1508.     if (p_verbose > 0)
  1509.     smsg((char_u *)_("Writing viminfo file \"%s\""), fname);
  1510.  
  1511.     viminfo_errcnt = 0;
  1512.     do_viminfo(fp_in, fp_out, !forceit, !forceit, FALSE);
  1513.  
  1514.     fclose(fp_out);        /* errors are ignored !? */
  1515.     if (fp_in != NULL)
  1516.     {
  1517.     fclose(fp_in);
  1518.     /*
  1519.      * In case of an error, don't overwrite the original viminfo file.
  1520.      */
  1521.     if (viminfo_errcnt || vim_rename(tempname, fname) == -1)
  1522.         mch_remove(tempname);
  1523.     }
  1524. end:
  1525.     vim_free(fname);
  1526.     vim_free(tempname);
  1527. }
  1528.  
  1529. /*
  1530.  * Get the viminfo file name to use.
  1531.  * If "file" is given and not empty, use it (has already been expanded by
  1532.  * cmdline functions).
  1533.  * Otherwise use "-i file_name", value from 'viminfo' or the default, and
  1534.  * expand environment variables.
  1535.  * Returns an allocated string.  NULL when out of memory.
  1536.  */
  1537.     static char_u *
  1538. viminfo_filename(file)
  1539.     char_u    *file;
  1540. {
  1541.     if (file == NULL || *file == NUL)
  1542.     {
  1543.     if (use_viminfo != NULL)
  1544.         file = use_viminfo;
  1545.     else if ((file = find_viminfo_parameter('n')) == NULL || *file == NUL)
  1546.     {
  1547. #ifdef VIMINFO_FILE2
  1548.         /* don't use $HOME when not defined (turned into "c:/"!). */
  1549. # ifdef VMS
  1550.         if (mch_getenv((char_u *)"SYS$LOGIN") == NULL)
  1551. # else
  1552.         if (mch_getenv((char_u *)"HOME") == NULL)
  1553. # endif
  1554.         {
  1555.         /* don't use $VIM when not available. */
  1556.         expand_env((char_u *)"$VIM", NameBuff, MAXPATHL);
  1557.         if (STRCMP("$VIM", NameBuff) != 0)  /* $VIM was expanded */
  1558.             file = (char_u *)VIMINFO_FILE2;
  1559.         else
  1560.             file = (char_u *)VIMINFO_FILE;
  1561.         }
  1562.         else
  1563. #endif
  1564.         file = (char_u *)VIMINFO_FILE;
  1565.     }
  1566.     expand_env(file, NameBuff, MAXPATHL);
  1567.     file = NameBuff;
  1568.     }
  1569.     return vim_strsave(file);
  1570. }
  1571.  
  1572. /*
  1573.  * do_viminfo() -- Should only be called from read_viminfo() & write_viminfo().
  1574.  */
  1575.     static void
  1576. do_viminfo(fp_in, fp_out, want_info, want_marks, force_read)
  1577.     FILE    *fp_in;
  1578.     FILE    *fp_out;
  1579.     int        want_info;
  1580.     int        want_marks;
  1581.     int        force_read;
  1582. {
  1583.     int        count = 0;
  1584.     int        eof = FALSE;
  1585.     vir_T    vir;
  1586.  
  1587.     if ((vir.vir_line = alloc(LSIZE)) == NULL)
  1588.     return;
  1589.     vir.vir_fd = fp_in;
  1590. #ifdef FEAT_MBYTE
  1591.     vir.vir_conv.vc_type = CONV_NONE;
  1592. # ifdef USE_ICONV
  1593.     vir.vir_conv.vc_fd = (iconv_t)-1;
  1594. # endif
  1595. #endif
  1596.  
  1597.     if (fp_in != NULL)
  1598.     {
  1599.     if (want_info)
  1600.         eof = read_viminfo_up_to_marks(&vir, force_read, fp_out != NULL);
  1601.     else
  1602.         /* Skip info, find start of marks */
  1603.         while (!(eof = viminfo_readline(&vir))
  1604.             && vir.vir_line[0] != '>')
  1605.         ;
  1606.     }
  1607.     if (fp_out != NULL)
  1608.     {
  1609.     /* Write the info: */
  1610.     fprintf(fp_out, _("# This viminfo file was generated by Vim %s.\n"),
  1611.                               VIM_VERSION_MEDIUM);
  1612.     fprintf(fp_out, _("# You may edit it if you're careful!\n\n"));
  1613. #ifdef FEAT_MBYTE
  1614.     fprintf(fp_out, _("# Value of 'encoding' when this file was written\n"));
  1615.     fprintf(fp_out, "*encoding=%s\n\n", p_enc);
  1616. #endif
  1617.     write_viminfo_search_pattern(fp_out);
  1618.     write_viminfo_sub_string(fp_out);
  1619. #ifdef FEAT_CMDHIST
  1620.     write_viminfo_history(fp_out);
  1621. #endif
  1622.     write_viminfo_registers(fp_out);
  1623. #ifdef FEAT_EVAL
  1624.     write_viminfo_varlist(fp_out);
  1625. #endif
  1626.     write_viminfo_filemarks(fp_out);
  1627.     write_viminfo_bufferlist(fp_out);
  1628.     count = write_viminfo_marks(fp_out);
  1629.     }
  1630.     if (fp_in != NULL && want_marks)
  1631.     copy_viminfo_marks(&vir, fp_out, count, eof);
  1632.  
  1633.     vim_free(vir.vir_line);
  1634. #ifdef FEAT_MBYTE
  1635.     if (vir.vir_conv.vc_type != CONV_NONE)
  1636.     convert_setup(&vir.vir_conv, (char_u *)"", (char_u *)"");
  1637. #endif
  1638. }
  1639.  
  1640. /*
  1641.  * read_viminfo_up_to_marks() -- Only called from do_viminfo().  Reads in the
  1642.  * first part of the viminfo file which contains everything but the marks that
  1643.  * are local to a file.  Returns TRUE when end-of-file is reached. -- webb
  1644.  */
  1645.     static int
  1646. read_viminfo_up_to_marks(virp, forceit, writing)
  1647.     vir_T    *virp;
  1648.     int        forceit;
  1649.     int        writing;
  1650. {
  1651.     int        eof;
  1652.     buf_T    *buf;
  1653.  
  1654. #ifdef FEAT_CMDHIST
  1655.     prepare_viminfo_history(forceit ? 9999 : 0);
  1656. #endif
  1657.     eof = viminfo_readline(virp);
  1658.     while (!eof && virp->vir_line[0] != '>')
  1659.     {
  1660.     switch (virp->vir_line[0])
  1661.     {
  1662.         /* Characters reserved for future expansion, ignored now */
  1663.         case '+': /* "+40 /path/dir file", for running vim without args */
  1664.         case '|': /* to be defined */
  1665.         case '^': /* to be defined */
  1666.         case '<': /* long line - ignored */
  1667.         /* A comment or empty line. */
  1668.         case NUL:
  1669.         case '\r':
  1670.         case '\n':
  1671.         case '#':
  1672.         eof = viminfo_readline(virp);
  1673.         break;
  1674.         case '*': /* "*encoding=value" */
  1675.         eof = viminfo_encoding(virp);
  1676.         break;
  1677.         case '!': /* global variable */
  1678. #ifdef FEAT_EVAL
  1679.         eof = read_viminfo_varlist(virp, writing);
  1680. #else
  1681.         eof = viminfo_readline(virp);
  1682. #endif
  1683.         break;
  1684.         case '%': /* entry for buffer list */
  1685.         eof = read_viminfo_bufferlist(virp, writing);
  1686.         break;
  1687.         case '"':
  1688.         eof = read_viminfo_register(virp, forceit);
  1689.         break;
  1690.         case '/':        /* Search string */
  1691.         case '&':        /* Substitute search string */
  1692.         case '~':        /* Last search string, followed by '/' or '&' */
  1693.         eof = read_viminfo_search_pattern(virp, forceit);
  1694.         break;
  1695.         case '$':
  1696.         eof = read_viminfo_sub_string(virp, forceit);
  1697.         break;
  1698.         case ':':
  1699.         case '?':
  1700.         case '=':
  1701.         case '@':
  1702. #ifdef FEAT_CMDHIST
  1703.         eof = read_viminfo_history(virp);
  1704. #else
  1705.         eof = viminfo_readline(virp);
  1706. #endif
  1707.         break;
  1708.         case '-':
  1709.         case '\'':
  1710.         eof = read_viminfo_filemark(virp, forceit);
  1711.         break;
  1712.         default:
  1713.         if (viminfo_error(_("Illegal starting char"), virp->vir_line))
  1714.             eof = TRUE;
  1715.         else
  1716.             eof = viminfo_readline(virp);
  1717.         break;
  1718.     }
  1719.     }
  1720.  
  1721. #ifdef FEAT_CMDHIST
  1722.     /* Finish reading history items. */
  1723.     finish_viminfo_history();
  1724. #endif
  1725.  
  1726.     /* Change file names to buffer numbers for fmarks. */
  1727.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  1728.     fmarks_check_names(buf);
  1729.  
  1730.     return eof;
  1731. }
  1732.  
  1733. /*
  1734.  * Compare the 'encoding' value in the viminfo file with the current value of
  1735.  * 'encoding'.  If different and the 'c' flag is in 'viminfo', setup for
  1736.  * conversion of text with iconv() in viminfo_readstring().
  1737.  */
  1738.     static int
  1739. viminfo_encoding(virp)
  1740.     vir_T    *virp;
  1741. {
  1742. #ifdef FEAT_MBYTE
  1743.     char_u    *p;
  1744.     int        i;
  1745.  
  1746.     if (get_viminfo_parameter('c') != 0)
  1747.     {
  1748.     p = vim_strchr(virp->vir_line, '=');
  1749.     if (p != NULL)
  1750.     {
  1751.         /* remove trailing newline */
  1752.         ++p;
  1753.         for (i = 0; vim_isprintc(p[i]); ++i)
  1754.         ;
  1755.         p[i] = NUL;
  1756.  
  1757.         convert_setup(&virp->vir_conv, p, p_enc);
  1758.     }
  1759.     }
  1760. #endif
  1761.     return viminfo_readline(virp);
  1762. }
  1763.  
  1764. /*
  1765.  * Read a line from the viminfo file.
  1766.  * Returns TRUE for end-of-file;
  1767.  */
  1768.     int
  1769. viminfo_readline(virp)
  1770.     vir_T    *virp;
  1771. {
  1772.     return vim_fgets(virp->vir_line, LSIZE, virp->vir_fd);
  1773. }
  1774.  
  1775. /*
  1776.  * check string read from viminfo file
  1777.  * remove '\n' at the end of the line
  1778.  * - replace CTRL-V CTRL-V with CTRL-V
  1779.  * - replace CTRL-V 'n'    with '\n'
  1780.  *
  1781.  * Check for a long line as written by viminfo_writestring().
  1782.  *
  1783.  * Return the string in allocated memory (NULL when out of memory).
  1784.  */
  1785. /*ARGSUSED*/
  1786.     char_u *
  1787. viminfo_readstring(virp, off, convert)
  1788.     vir_T    *virp;
  1789.     int        off;            /* offset for virp->vir_line */
  1790.     int        convert;        /* convert the string */
  1791. {
  1792.     char_u    *retval;
  1793.     char_u    *s, *d;
  1794.     long    len;
  1795.  
  1796.     if (virp->vir_line[off] == Ctrl_V && isdigit(virp->vir_line[off + 1]))
  1797.     {
  1798.     len = atol((char *)virp->vir_line + off + 1);
  1799.     retval = lalloc(len, TRUE);
  1800.     if (retval == NULL)
  1801.     {
  1802.         /* Line too long?  File messed up?  Skip next line. */
  1803.         (void)vim_fgets(virp->vir_line, 10, virp->vir_fd);
  1804.         return NULL;
  1805.     }
  1806.     (void)vim_fgets(retval, (int)len, virp->vir_fd);
  1807.     s = retval + 1;        /* Skip the leading '<' */
  1808.     }
  1809.     else
  1810.     {
  1811.     retval = vim_strsave(virp->vir_line + off);
  1812.     if (retval == NULL)
  1813.         return NULL;
  1814.     s = retval;
  1815.     }
  1816.  
  1817.     /* Change CTRL-V CTRL-V to CTRL-V and CTRL-V n to \n in-place. */
  1818.     d = retval;
  1819.     while (*s != NUL && *s != '\n')
  1820.     {
  1821.     if (s[0] == Ctrl_V && s[1] != NUL)
  1822.     {
  1823.         if (s[1] == 'n')
  1824.         *d++ = '\n';
  1825.         else
  1826.         *d++ = Ctrl_V;
  1827.         s += 2;
  1828.     }
  1829.     else
  1830.         *d++ = *s++;
  1831.     }
  1832.     *d = NUL;
  1833.  
  1834. #ifdef FEAT_MBYTE
  1835.     if (convert && virp->vir_conv.vc_type != CONV_NONE)
  1836.     {
  1837.     d = string_convert(&virp->vir_conv, retval, NULL);
  1838.     if (d != NULL)
  1839.     {
  1840.         vim_free(retval);
  1841.         retval = d;
  1842.     }
  1843.     }
  1844. #endif
  1845.  
  1846.     return retval;
  1847. }
  1848.  
  1849. /*
  1850.  * write string to viminfo file
  1851.  * - replace CTRL-V with CTRL-V CTRL-V
  1852.  * - replace '\n'   with CTRL-V 'n'
  1853.  * - add a '\n' at the end
  1854.  *
  1855.  * For a long line:
  1856.  * - write " CTRL-V <length> \n " in first line
  1857.  * - write " < <string> \n "      in second line
  1858.  */
  1859.     void
  1860. viminfo_writestring(fd, p)
  1861.     FILE    *fd;
  1862.     char_u    *p;
  1863. {
  1864.     int        c;
  1865.     char_u    *s;
  1866.     int        len = 0;
  1867.  
  1868.     for (s = p; *s != NUL; ++s)
  1869.     {
  1870.     if (*s == Ctrl_V || *s == '\n')
  1871.         ++len;
  1872.     ++len;
  1873.     }
  1874.  
  1875.     /* If the string will be too long, write its length and put it in the next
  1876.      * line.  Take into account that some room is needed for what comes before
  1877.      * the string (e.g., variable name).  Add something to the length for the
  1878.      * '<', NL and trailing NUL. */
  1879.     if (len > LSIZE / 2)
  1880.     fprintf(fd, IF_EB("\026%d\n<", CTRL_V_STR "%d\n<"), len + 3);
  1881.  
  1882.     while ((c = *p++) != NUL)
  1883.     {
  1884.     if (c == Ctrl_V || c == '\n')
  1885.     {
  1886.         putc(Ctrl_V, fd);
  1887.         if (c == '\n')
  1888.         c = 'n';
  1889.     }
  1890.     putc(c, fd);
  1891.     }
  1892.     putc('\n', fd);
  1893. }
  1894. #endif /* FEAT_VIMINFO */
  1895.  
  1896. /*
  1897.  * Implementation of ":fixdel", also used by get_stty().
  1898.  *  <BS>    resulting <Del>
  1899.  *   ^?        ^H
  1900.  * not ^?    ^?
  1901.  */
  1902. /*ARGSUSED*/
  1903.     void
  1904. do_fixdel(eap)
  1905.     exarg_T    *eap;
  1906. {
  1907.     char_u  *p;
  1908.  
  1909.     p = find_termcode((char_u *)"kb");
  1910.     add_termcode((char_u *)"kD", p != NULL
  1911.         && *p == DEL ? (char_u *)CTRL_H_STR : DEL_STR, FALSE);
  1912. }
  1913.  
  1914.     void
  1915. print_line_no_prefix(lnum, use_number)
  1916.     linenr_T    lnum;
  1917.     int        use_number;
  1918. {
  1919.     char_u    numbuf[20];
  1920.  
  1921.     if (curwin->w_p_nu || use_number)
  1922.     {
  1923.     sprintf((char *)numbuf, "%7ld ", (long)lnum);
  1924.     msg_puts_attr(numbuf, hl_attr(HLF_N));    /* Highlight line nrs */
  1925.     }
  1926.     msg_prt_line(ml_get(lnum));
  1927. }
  1928.  
  1929. /*
  1930.  * Print a text line.  Also in silent mode ("ex -s").
  1931.  */
  1932.     void
  1933. print_line(lnum, use_number)
  1934.     linenr_T    lnum;
  1935.     int        use_number;
  1936. {
  1937.     int        save_silent = silent_mode;
  1938.  
  1939.     silent_mode = FALSE;
  1940.     msg_start();
  1941.     print_line_no_prefix(lnum, use_number);
  1942.     if (save_silent)
  1943.     {
  1944.     msg_putchar('\n');
  1945.     cursor_on();        /* msg_start() switches it off */
  1946.     out_flush();
  1947.     silent_mode = save_silent;
  1948.     }
  1949. }
  1950.  
  1951. /*
  1952.  * ":file[!] [fname]".
  1953.  */
  1954.     void
  1955. ex_file(eap)
  1956.     exarg_T    *eap;
  1957. {
  1958.     char_u    *fname, *sfname, *xfname;
  1959.     buf_T    *buf;
  1960.  
  1961.     if (*eap->arg != NUL)
  1962.     {
  1963. #ifdef FEAT_AUTOCMD
  1964.     buf = curbuf;
  1965.     apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, FALSE, curbuf);
  1966.     /* buffer changed, don't change name now */
  1967.     if (buf != curbuf)
  1968.         return;
  1969. #endif
  1970.     /*
  1971.      * The name of the current buffer will be changed.
  1972.      * A new buffer entry needs to be made to hold the old
  1973.      * file name, which will become the alternate file name.
  1974.      */
  1975.     fname = curbuf->b_ffname;
  1976.     sfname = curbuf->b_sfname;
  1977.     xfname = curbuf->b_fname;
  1978.     curbuf->b_ffname = NULL;
  1979.     curbuf->b_sfname = NULL;
  1980.     if (setfname(eap->arg, NULL, TRUE) == FAIL)
  1981.     {
  1982.         curbuf->b_ffname = fname;
  1983.         curbuf->b_sfname = sfname;
  1984.         return;
  1985.     }
  1986.     curbuf->b_flags |= BF_NOTEDITED;
  1987.     buf = buflist_new(fname, xfname, curwin->w_cursor.lnum, BLN_LISTED);
  1988.     if (buf != NULL)
  1989.         curwin->w_alt_fnum = buf->b_fnum;
  1990.     vim_free(fname);
  1991.     vim_free(sfname);
  1992. #ifdef FEAT_AUTOCMD
  1993.     apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, FALSE, curbuf);
  1994. #endif
  1995.     }
  1996.     /* print full file name if :cd used */
  1997.     fileinfo(FALSE, FALSE, eap->forceit);
  1998. }
  1999.  
  2000. /*
  2001.  * ":update".
  2002.  */
  2003.     void
  2004. ex_update(eap)
  2005.     exarg_T    *eap;
  2006. {
  2007.     if (curbufIsChanged())
  2008.     (void)do_write(eap);
  2009. }
  2010.  
  2011. /*
  2012.  * ":write" and ":saveas".
  2013.  */
  2014.     void
  2015. ex_write(eap)
  2016.     exarg_T    *eap;
  2017. {
  2018.     if (eap->usefilter)        /* input lines to shell command */
  2019.     do_bang(1, eap, FALSE, TRUE, FALSE);
  2020.     else
  2021.     (void)do_write(eap);
  2022. }
  2023.  
  2024. /*
  2025.  * write current buffer to file 'eap->arg'
  2026.  * if 'eap->append' is TRUE, append to the file
  2027.  *
  2028.  * if *eap->arg == NUL write to current file
  2029.  *
  2030.  * return FAIL for failure, OK otherwise
  2031.  */
  2032.     int
  2033. do_write(eap)
  2034.     exarg_T    *eap;
  2035. {
  2036.     int        other;
  2037.     char_u    *fname = NULL;        /* init to shut up gcc */
  2038.     char_u    *ffname;
  2039.     int        retval = FAIL;
  2040.     char_u    *free_fname = NULL;
  2041. #ifdef FEAT_BROWSE
  2042.     char_u    *browse_file = NULL;
  2043. #endif
  2044.     buf_T    *alt_buf = NULL;
  2045.  
  2046.     if (not_writing())        /* check 'write' option */
  2047.     return FAIL;
  2048.  
  2049.     ffname = eap->arg;
  2050. #ifdef FEAT_BROWSE
  2051.     if (cmdmod.browse)
  2052.     {
  2053.     browse_file = do_browse(TRUE, (char_u *)_("Save As"), NULL,
  2054.                           NULL, ffname, NULL, curbuf);
  2055.     if (browse_file == NULL)
  2056.         goto theend;
  2057.     ffname = browse_file;
  2058.     }
  2059. #endif
  2060.     if (*ffname == NUL)
  2061.     {
  2062.     if (eap->cmdidx == CMD_saveas)
  2063.     {
  2064.         EMSG(_(e_argreq));
  2065.         goto theend;
  2066.     }
  2067.     other = FALSE;
  2068.     }
  2069.     else
  2070.     {
  2071.     fname = ffname;
  2072.     free_fname = fix_fname(ffname);
  2073.     /*
  2074.      * When out-of-memory, keep unexpanded file name, because we MUST be
  2075.      * able to write the file in this situation.
  2076.      */
  2077.     if (free_fname != NULL)
  2078.         ffname = free_fname;
  2079.     other = otherfile(ffname);
  2080.     }
  2081.  
  2082.     /*
  2083.      * If we have a new file, put its name in the list of alternate file names.
  2084.      */
  2085.     if (other)
  2086.     {
  2087.     if (vim_strchr(p_cpo, CPO_ALTWRITE) != NULL
  2088.                          || eap->cmdidx == CMD_saveas)
  2089.         alt_buf = setaltfname(ffname, fname, (linenr_T)1);
  2090.     else
  2091.         alt_buf = buflist_findname(ffname);
  2092.     if (alt_buf != NULL && alt_buf->b_ml.ml_mfp != NULL)
  2093.     {
  2094.         /* Overwriting a file that is loaded in another buffer is not a
  2095.          * good idea. */
  2096.         EMSG(_("E139: File is loaded in another buffer"));
  2097.         goto theend;
  2098.     }
  2099.     }
  2100.  
  2101.     /*
  2102.      * Writing to the current file is not allowed in readonly mode
  2103.      * and a file name is required.
  2104.      * "nofile" and "nowrite" buffers cannot be written implicitly either.
  2105.      */
  2106.     if (!other && (
  2107. #ifdef FEAT_QUICKFIX
  2108.         bt_dontwrite_msg(curbuf) ||
  2109. #endif
  2110.         check_fname() == FAIL || check_readonly(&eap->forceit, curbuf)))
  2111.     goto theend;
  2112.  
  2113.     if (!other)
  2114.     {
  2115.     ffname = curbuf->b_ffname;
  2116.     fname = curbuf->b_fname;
  2117.     /*
  2118.      * Not writing the whole file is only allowed with '!'.
  2119.      */
  2120.     if (       (eap->line1 != 1
  2121.             || eap->line2 != curbuf->b_ml.ml_line_count)
  2122.         && !eap->forceit
  2123.         && !eap->append
  2124.         && !p_wa)
  2125.     {
  2126. #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
  2127.         if (p_confirm || cmdmod.confirm)
  2128.         {
  2129.         if (vim_dialog_yesno(VIM_QUESTION, NULL,
  2130.                    (char_u *)_("Write partial file?"), 2) != VIM_YES)
  2131.             goto theend;
  2132.         eap->forceit = TRUE;
  2133.         }
  2134.         else
  2135. #endif
  2136.         {
  2137.         EMSG(_("E140: Use ! to write partial buffer"));
  2138.         goto theend;
  2139.         }
  2140.     }
  2141.     }
  2142.  
  2143.     if (eap->cmdidx == CMD_saveas && alt_buf != NULL)
  2144.     {
  2145.     /* Exchange the file names for the current and the alternate buffer.
  2146.      * This makes it look like we are now editing the buffer under the new
  2147.      * name.  Must be done before buf_write(), because if there is no file
  2148.      * name and 'cpo' contains 'F', it will set the file name. */
  2149.     fname = alt_buf->b_fname;
  2150.     alt_buf->b_fname = curbuf->b_fname;
  2151.     curbuf->b_fname = fname;
  2152.     fname = alt_buf->b_ffname;
  2153.     alt_buf->b_ffname = curbuf->b_ffname;
  2154.     curbuf->b_ffname = fname;
  2155.     fname = alt_buf->b_sfname;
  2156.     alt_buf->b_sfname = curbuf->b_sfname;
  2157.     curbuf->b_sfname = fname;
  2158.     buf_name_changed();
  2159. #ifdef FEAT_AUTOCMD
  2160.     if (!alt_buf->b_p_bl)
  2161.     {
  2162.         alt_buf->b_p_bl = TRUE;
  2163.         apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, curbuf);
  2164.     }
  2165. #endif
  2166.     }
  2167.  
  2168.     if (check_overwrite(eap, curbuf, fname, ffname, other) == OK)
  2169.     retval = buf_write(curbuf, ffname, fname, eap->line1, eap->line2,
  2170.                  eap, eap->append, eap->forceit, TRUE, FALSE);
  2171.  
  2172. theend:
  2173. #ifdef FEAT_BROWSE
  2174.     vim_free(browse_file);
  2175. #endif
  2176.     vim_free(free_fname);
  2177.     return retval;
  2178. }
  2179.  
  2180. /*
  2181.  * Check if it is allowed to overwrite a file.  If b_flags has BF_NOTEDITED,
  2182.  * BF_NEW or BF_READERR, check for overwriting current file.
  2183.  * May set eap->forceit if a dialog says it's OK to overwrite.
  2184.  * Return OK if it's OK, FAIL if it is not.
  2185.  */
  2186. /*ARGSUSED*/
  2187.     static int
  2188. check_overwrite(eap, buf, fname, ffname, other)
  2189.     exarg_T    *eap;
  2190.     buf_T    *buf;
  2191.     char_u    *fname;        /* file name to be used (can differ from
  2192.                    buf->ffname) */
  2193.     char_u    *ffname;    /* full path version of fname */
  2194.     int        other;        /* writing under other name */
  2195. {
  2196.     /*
  2197.      * write to other file or b_flags set or not writing the whole file:
  2198.      * overwriting only allowed with '!'
  2199.      */
  2200.     if (       (other
  2201.         || (buf->b_flags & BF_NOTEDITED)
  2202.         || ((buf->b_flags & BF_NEW)
  2203.             && vim_strchr(p_cpo, CPO_OVERNEW) == NULL)
  2204.         || (buf->b_flags & BF_READERR))
  2205.         && !eap->forceit
  2206.         && !eap->append
  2207.         && !p_wa
  2208.         && vim_fexists(ffname))
  2209.     {
  2210. #ifdef UNIX
  2211.         /* with UNIX it is possible to open a directory */
  2212.     if (mch_isdir(ffname))
  2213.     {
  2214.         EMSG2(_(e_isadir2), ffname);
  2215.         return FAIL;
  2216.     }
  2217. #endif
  2218. #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
  2219.     if (p_confirm || cmdmod.confirm)
  2220.     {
  2221.         char_u    buff[IOSIZE];
  2222.  
  2223.         dialog_msg(buff, _("Overwrite existing file \"%.*s\"?"), fname);
  2224.         if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2) != VIM_YES)
  2225.         return FAIL;
  2226.         eap->forceit = TRUE;
  2227.     }
  2228.     else
  2229. #endif
  2230.     {
  2231.         EMSG(_(e_exists));
  2232.         return FAIL;
  2233.     }
  2234.     }
  2235.     return OK;
  2236. }
  2237.  
  2238. /*
  2239.  * Handle ":wnext", ":wNext" and ":wprevious" commands.
  2240.  */
  2241.     void
  2242. ex_wnext(eap)
  2243.     exarg_T    *eap;
  2244. {
  2245.     int        i;
  2246.  
  2247.     if (eap->cmd[1] == 'n')
  2248.     i = curwin->w_arg_idx + (int)eap->line2;
  2249.     else
  2250.     i = curwin->w_arg_idx - (int)eap->line2;
  2251.     eap->line1 = 1;
  2252.     eap->line2 = curbuf->b_ml.ml_line_count;
  2253.     if (do_write(eap) != FAIL)
  2254.     do_argfile(eap, i);
  2255. }
  2256.  
  2257. /*
  2258.  * ":wall", ":wqall" and ":xall": Write all changed files (and exit).
  2259.  */
  2260.     void
  2261. do_wqall(eap)
  2262.     exarg_T    *eap;
  2263. {
  2264.     buf_T    *buf;
  2265.     int        error = 0;
  2266.  
  2267.     if (eap->cmdidx == CMD_xall || eap->cmdidx == CMD_wqall)
  2268.     exiting = TRUE;
  2269.  
  2270.     for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  2271.     {
  2272.     if (bufIsChanged(buf))
  2273.     {
  2274.         /*
  2275.          * Check if there is a reason the buffer cannot be written:
  2276.          * 1. if the 'write' option is set
  2277.          * 2. if there is no file name (even after browsing)
  2278.          * 3. if the 'readonly' is set (even after a dialog)
  2279.          * 4. if overwriting is allowed (even after a dialog)
  2280.          */
  2281.         if (not_writing())
  2282.         {
  2283.         ++error;
  2284.         break;
  2285.         }
  2286. #ifdef FEAT_BROWSE
  2287.         /* ":browse wall": ask for file name if there isn't one */
  2288.         if (buf->b_ffname == NULL && cmdmod.browse)
  2289.         buf->b_ffname = do_browse(TRUE, (char_u *)_("Save As"), NULL,
  2290.                            NULL, (char_u *)"", NULL, buf);
  2291. #endif
  2292.         if (buf->b_ffname == NULL)
  2293.         {
  2294.         EMSGN(_("E141: No file name for buffer %ld"), (long)buf->b_fnum);
  2295.         ++error;
  2296.         }
  2297.         else if (check_readonly(&eap->forceit, buf)
  2298.             || check_overwrite(eap, buf, buf->b_fname, buf->b_ffname,
  2299.                                    FALSE) == FAIL)
  2300.         {
  2301.         ++error;
  2302.         }
  2303.         else
  2304.         {
  2305.         if (buf_write_all(buf, eap->forceit) == FAIL)
  2306.             ++error;
  2307. #ifdef FEAT_AUTOCMD
  2308.         /* an autocommand may have deleted the buffer */
  2309.         if (!buf_valid(buf))
  2310.             buf = firstbuf;
  2311. #endif
  2312.         }
  2313.     }
  2314.     }
  2315.     if (exiting)
  2316.     {
  2317.     if (!error)
  2318.         getout(0);        /* exit Vim */
  2319.     not_exiting();
  2320.     }
  2321. }
  2322.  
  2323. /*
  2324.  * Check the 'write' option.
  2325.  * Return TRUE and give a message when it's not st.
  2326.  */
  2327.     int
  2328. not_writing()
  2329. {
  2330.     if (p_write)
  2331.     return FALSE;
  2332.     EMSG(_("E142: File not written: Writing is disabled by 'write' option"));
  2333.     return TRUE;
  2334. }
  2335.  
  2336. /*
  2337.  * Check if a buffer is read-only.  Ask for overruling in a dialog.
  2338.  * Return TRUE and give an error message when the buffer is readonly.
  2339.  */
  2340.     static int
  2341. check_readonly(forceit, buf)
  2342.     int        *forceit;
  2343.     buf_T    *buf;
  2344. {
  2345.     if (!*forceit && buf->b_p_ro)
  2346.     {
  2347. #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
  2348.     if ((p_confirm || cmdmod.confirm) && buf->b_fname != NULL)
  2349.     {
  2350.         char_u    buff[IOSIZE];
  2351.  
  2352.         dialog_msg(buff, _("'readonly' option is set for \"%.*s\".\nDo you wish to write anyway?"),
  2353.             buf->b_fname);
  2354.  
  2355.         if (vim_dialog_yesno(VIM_QUESTION, NULL, buff, 2) == VIM_YES)
  2356.         {
  2357.         /* Set forceit, to force the writing of a readonly file */
  2358.         *forceit = TRUE;
  2359.         return FALSE;
  2360.         }
  2361.         else
  2362.         return TRUE;
  2363.     }
  2364.     else
  2365. #endif
  2366.         EMSG(_(e_readonly));
  2367.     return TRUE;
  2368.     }
  2369.     return FALSE;
  2370. }
  2371.  
  2372. /*
  2373.  * try to abandon current file and edit a new or existing file
  2374.  * 'fnum' is the number of the file, if zero use ffname/sfname
  2375.  *
  2376.  * return 1 for "normal" error, 2 for "not written" error, 0 for success
  2377.  * -1 for succesfully opening another file
  2378.  * 'lnum' is the line number for the cursor in the new file (if non-zero).
  2379.  */
  2380.     int
  2381. getfile(fnum, ffname, sfname, setpm, lnum, forceit)
  2382.     int        fnum;
  2383.     char_u    *ffname;
  2384.     char_u    *sfname;
  2385.     int        setpm;
  2386.     linenr_T    lnum;
  2387.     int        forceit;
  2388. {
  2389.     int        other;
  2390.     int        retval;
  2391.     char_u    *free_me = NULL;
  2392.  
  2393. #ifdef FEAT_CMDWIN
  2394.     if (cmdwin_type != 0)
  2395.     return 1;
  2396. #endif
  2397.  
  2398.     if (fnum == 0)
  2399.     {
  2400.     fname_expand(&ffname, &sfname);    /* make ffname full path, set sfname */
  2401.     other = otherfile(ffname);
  2402.     free_me = ffname;        /* has been allocated, free() later */
  2403.     }
  2404.     else
  2405.     other = (fnum != curbuf->b_fnum);
  2406.  
  2407.     if (other)
  2408.     ++no_wait_return;        /* don't wait for autowrite message */
  2409.     if (other && !forceit && curbuf->b_nwindows == 1 && !P_HID(curbuf)
  2410.            && curbufIsChanged() && autowrite(curbuf, forceit) == FAIL)
  2411.     {
  2412.     if (other)
  2413.         --no_wait_return;
  2414.     EMSG(_(e_nowrtmsg));
  2415.     retval = 2;    /* file has been changed */
  2416.     goto theend;
  2417.     }
  2418.     if (other)
  2419.     --no_wait_return;
  2420.     if (setpm)
  2421.     setpcmark();
  2422.     if (!other)
  2423.     {
  2424.     if (lnum != 0)
  2425.         curwin->w_cursor.lnum = lnum;
  2426.     check_cursor_lnum();
  2427.     beginline(BL_SOL | BL_FIX);
  2428.     retval = 0;    /* it's in the same file */
  2429.     }
  2430.     else if (do_ecmd(fnum, ffname, sfname, NULL, lnum,
  2431.         (P_HID(curbuf) ? ECMD_HIDE : 0) + (forceit ? ECMD_FORCEIT : 0)) == OK)
  2432.     retval = -1;    /* opened another file */
  2433.     else
  2434.     retval = 1;    /* error encountered */
  2435.  
  2436. theend:
  2437.     vim_free(free_me);
  2438.     return retval;
  2439. }
  2440.  
  2441. /*
  2442.  * start editing a new file
  2443.  *
  2444.  *     fnum: file number; if zero use ffname/sfname
  2445.  *   ffname: the file name
  2446.  *        - full path if sfname used,
  2447.  *        - any file name if sfname is NULL
  2448.  *        - empty string to re-edit with the same file name (but may be
  2449.  *            in a different directory)
  2450.  *        - NULL to start an empty buffer
  2451.  *   sfname: the short file name (or NULL)
  2452.  *    eap: contains the command to be executed after loading the file and
  2453.  *         forced 'ff' and 'fenc'
  2454.  *  newlnum: if > 0: put cursor on this line number (if possible)
  2455.  *         if ECMD_LASTL: use last position in loaded file
  2456.  *         if ECMD_LAST: use last position in all files
  2457.  *         if ECMD_ONE: use first line
  2458.  *    flags:
  2459.  *       ECMD_HIDE: if TRUE don't free the current buffer
  2460.  *     ECMD_SET_HELP: set b_help flag of (new) buffer before opening file
  2461.  *     ECMD_OLDBUF: use existing buffer if it exists
  2462.  *    ECMD_FORCEIT: ! used for Ex command
  2463.  *     ECMD_ADDBUF: don't edit, just add to buffer list
  2464.  *
  2465.  * return FAIL for failure, OK otherwise
  2466.  */
  2467.     int
  2468. do_ecmd(fnum, ffname, sfname, eap, newlnum, flags)
  2469.     int        fnum;
  2470.     char_u    *ffname;
  2471.     char_u    *sfname;
  2472.     exarg_T    *eap;            /* can be NULL! */
  2473.     linenr_T    newlnum;
  2474.     int        flags;
  2475. {
  2476.     int        other_file;        /* TRUE if editing another file */
  2477.     int        oldbuf;            /* TRUE if using existing buffer */
  2478. #ifdef FEAT_AUTOCMD
  2479.     int        auto_buf = FALSE;    /* TRUE if autocommands brought us
  2480.                        into the buffer unexpectedly */
  2481.     char_u    *new_name = NULL;
  2482. #endif
  2483.     buf_T    *buf;
  2484. #if defined(FEAT_AUTOCMD) || defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
  2485.     buf_T    *old_curbuf = curbuf;
  2486. #endif
  2487.     char_u    *free_fname = NULL;
  2488. #ifdef FEAT_BROWSE
  2489.     char_u    *browse_file = NULL;
  2490. #endif
  2491.     int        retval = FAIL;
  2492.     long    n;
  2493.     linenr_T    lnum;
  2494.     linenr_T    topline = 0;
  2495.     int        newcol = -1;
  2496.     int        solcol = -1;
  2497.     pos_T    *pos;
  2498. #ifdef FEAT_SUN_WORKSHOP
  2499.     char_u    *cp;
  2500. #endif
  2501.     char_u    *command = NULL;
  2502.  
  2503.     if (eap != NULL)
  2504.     command = eap->do_ecmd_cmd;
  2505.  
  2506.     if (fnum != 0)
  2507.     {
  2508.     if (fnum == curbuf->b_fnum)    /* file is already being edited */
  2509.         return OK;            /* nothing to do */
  2510.     other_file = TRUE;
  2511.     }
  2512.     else
  2513.     {
  2514. #ifdef FEAT_BROWSE
  2515.     if (cmdmod.browse)
  2516.     {
  2517.         browse_file = do_browse(FALSE, (char_u *)_("Edit File"), NULL,
  2518.                           NULL, ffname, NULL, curbuf);
  2519.         if (browse_file == NULL)
  2520.         goto theend;
  2521.         ffname = browse_file;
  2522.     }
  2523. #endif
  2524.     /* if no short name given, use ffname for short name */
  2525.     if (sfname == NULL)
  2526.         sfname = ffname;
  2527. #ifdef USE_FNAME_CASE
  2528. # ifdef USE_LONG_FNAME
  2529.     if (USE_LONG_FNAME)
  2530. # endif
  2531.         fname_case(sfname, 0);   /* set correct case for short file name */
  2532. #endif
  2533.  
  2534. #ifdef FEAT_LISTCMDS
  2535.     if ((flags & ECMD_ADDBUF) && (ffname == NULL || *ffname == NUL))
  2536.         goto theend;
  2537. #endif
  2538.  
  2539.     if (ffname == NULL)
  2540.         other_file = TRUE;
  2541.                         /* there is no file name */
  2542.     else if (*ffname == NUL && curbuf->b_ffname == NULL)
  2543.         other_file = FALSE;
  2544.     else
  2545.     {
  2546.         if (*ffname == NUL)            /* re-edit with same file name */
  2547.         {
  2548.         ffname = curbuf->b_ffname;
  2549.         sfname = curbuf->b_fname;
  2550.         }
  2551.         free_fname = fix_fname(ffname); /* may expand to full path name */
  2552.         if (free_fname != NULL)
  2553.         ffname = free_fname;
  2554.         other_file = otherfile(ffname);
  2555. #ifdef FEAT_SUN_WORKSHOP
  2556.         if (usingSunWorkShop && (cp = vim_strrchr(sfname, '/')) != NULL)
  2557.         sfname = ++cp;
  2558. #endif
  2559.     }
  2560.     }
  2561.  
  2562.     /*
  2563.      * if the file was changed we may not be allowed to abandon it
  2564.      * - if we are going to re-edit the same file
  2565.      * - or if we are the only window on this file and if ECMD_HIDE is FALSE
  2566.      */
  2567.     if (  ((!other_file && !(flags & ECMD_OLDBUF))
  2568.         || (curbuf->b_nwindows == 1
  2569.         && !(flags & (ECMD_HIDE | ECMD_ADDBUF))))
  2570.     && check_changed(curbuf, p_awa, !other_file,
  2571.                     (flags & ECMD_FORCEIT), FALSE))
  2572.     {
  2573.     if (fnum == 0 && other_file && ffname != NULL)
  2574.         (void)setaltfname(ffname, sfname, newlnum < 0 ? 0 : newlnum);
  2575.     goto theend;
  2576.     }
  2577.  
  2578. #ifdef FEAT_VISUAL
  2579.     /*
  2580.      * End Visual mode before switching to another buffer, so the text can be
  2581.      * copied into the GUI selection buffer.
  2582.      */
  2583.     reset_VIsual();
  2584. #endif
  2585.  
  2586.     /*
  2587.      * If we are starting to edit another file, open a (new) buffer.
  2588.      * Otherwise we re-use the current buffer.
  2589.      */
  2590.     if (other_file)
  2591.     {
  2592. #ifdef FEAT_LISTCMDS
  2593.     if (!(flags & ECMD_ADDBUF))
  2594. #endif
  2595.     {
  2596.         curwin->w_alt_fnum = curbuf->b_fnum;
  2597.         buflist_altfpos();
  2598.     }
  2599.  
  2600.     if (fnum)
  2601.         buf = buflist_findnr(fnum);
  2602.     else
  2603.     {
  2604. #ifdef FEAT_LISTCMDS
  2605.         if (flags & ECMD_ADDBUF)
  2606.         {
  2607.         linenr_T    tlnum = 1L;
  2608.  
  2609.         if (command != NULL)
  2610.         {
  2611.             tlnum = atol((char *)command);
  2612.             if (tlnum <= 0)
  2613.             tlnum = 1L;
  2614.         }
  2615.         (void)buflist_new(ffname, sfname, tlnum, BLN_LISTED);
  2616.         goto theend;
  2617.         }
  2618. #endif
  2619.         buf = buflist_new(ffname, sfname, 0L,
  2620.             BLN_CURBUF | ((flags & ECMD_SET_HELP) ? 0 : BLN_LISTED));
  2621.     }
  2622.     if (buf == NULL)
  2623.         goto theend;
  2624.     if (buf->b_ml.ml_mfp == NULL)        /* no memfile yet */
  2625.     {
  2626.         oldbuf = FALSE;
  2627.         buf->b_nwindows = 0;
  2628.     }
  2629.     else                    /* existing memfile */
  2630.     {
  2631.         oldbuf = TRUE;
  2632.         (void)buf_check_timestamp(buf, FALSE);
  2633.         /* Check if autocommands made buffer invalid. */
  2634.         if (!buf_valid(buf))
  2635.         goto theend;
  2636.     }
  2637.  
  2638.     /* May jump to last used line number for a loaded buffer or when asked
  2639.      * for explicitly */
  2640.     if ((oldbuf && newlnum == ECMD_LASTL) || newlnum == ECMD_LAST)
  2641.     {
  2642.         pos = buflist_findfpos(buf);
  2643.         newlnum = pos->lnum;
  2644.         solcol = pos->col;
  2645.     }
  2646.  
  2647.     /*
  2648.      * Make the (new) buffer the one used by the current window.
  2649.      * If the old buffer becomes unused, free it if ECMD_HIDE is FALSE.
  2650.      * If the current buffer was empty and has no file name, curbuf
  2651.      * is returned by buflist_new().
  2652.      */
  2653.     if (buf != curbuf)
  2654.     {
  2655. #ifdef FEAT_AUTOCMD
  2656.         /*
  2657.          * Be careful: The autocommands may delete any buffer and change
  2658.          * the current buffer.
  2659.          * - If the buffer we are going to edit is deleted, give up.
  2660.          * - If the current buffer is deleted, prefer to load the new
  2661.          *   buffer when loading a buffer is required.  This avoids
  2662.          *   loading another buffer which then must be closed again.
  2663.          * - If we ended up in the new buffer already, need to skip a few
  2664.          *     things, set auto_buf.
  2665.          */
  2666.         if (buf->b_fname != NULL)
  2667.         new_name = vim_strsave(buf->b_fname);
  2668.         au_new_curbuf = buf;
  2669.         apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
  2670.         if (!buf_valid(buf))    /* new buffer has been deleted */
  2671.         {
  2672.         delbuf_msg(new_name);    /* frees new_name */
  2673.         goto theend;
  2674.         }
  2675.         if (buf == curbuf)        /* already in new buffer */
  2676.         auto_buf = TRUE;
  2677.         else
  2678.         {
  2679.         if (curbuf == old_curbuf)
  2680. #endif
  2681.             buf_copy_options(buf, BCO_ENTER);
  2682.  
  2683.         /* close the link to the current buffer */
  2684.         close_buffer(curwin, curbuf,
  2685.                       (flags & ECMD_HIDE) ? 0 : DOBUF_UNLOAD);
  2686.  
  2687. #ifdef FEAT_AUTOCMD
  2688.         /* Be careful again, like above. */
  2689.         if (!buf_valid(buf))    /* new buffer has been deleted */
  2690.         {
  2691.             delbuf_msg(new_name);    /* frees new_name */
  2692.             goto theend;
  2693.         }
  2694.         if (buf == curbuf)        /* already in new buffer */
  2695.             auto_buf = TRUE;
  2696.         else
  2697. #endif
  2698.  
  2699.         {
  2700.             curwin->w_buffer = buf;
  2701.             curbuf = buf;
  2702.             ++curbuf->b_nwindows;
  2703.             /* set 'fileformat' */
  2704.             if (*p_ffs && !oldbuf)
  2705.             set_fileformat(default_fileformat(), OPT_LOCAL);
  2706.         }
  2707.  
  2708.         /* May get the window options from the last time this buffer
  2709.          * was in this window (or another window).  If not used
  2710.          * before, reset the local window options to the global
  2711.          * values.  Also restores old folding stuff. */
  2712.         get_winopts(buf);
  2713.  
  2714. #ifdef FEAT_AUTOCMD
  2715.         }
  2716.         vim_free(new_name);
  2717.         au_new_curbuf = NULL;
  2718. #endif
  2719.     }
  2720.     else
  2721.         ++curbuf->b_nwindows;
  2722.  
  2723.     curwin->w_pcmark.lnum = 1;
  2724.     curwin->w_pcmark.col = 0;
  2725.     }
  2726.     else /* !other_file */
  2727.     {
  2728.     if (
  2729. #ifdef FEAT_LISTCMDS
  2730.         (flags & ECMD_ADDBUF) ||
  2731. #endif
  2732.         check_fname() == FAIL)
  2733.         goto theend;
  2734.     oldbuf = (flags & ECMD_OLDBUF);
  2735.     }
  2736.  
  2737.     if ((flags & ECMD_SET_HELP) || keep_help_flag)
  2738.     {
  2739.     curbuf->b_help = TRUE;
  2740. #ifdef FEAT_QUICKFIX
  2741.     set_string_option_direct((char_u *)"buftype", -1,
  2742.                        (char_u *)"help", OPT_FREE |OPT_LOCAL);
  2743. #endif
  2744.     curbuf->b_p_ma = FALSE;
  2745.     curbuf->b_p_bin = FALSE;    /* reset 'bin' before reading file */
  2746.     curwin->w_p_nu = 0;        /* no line numbers */
  2747. #ifdef FEAT_RIGHTLEFT
  2748.     curwin->w_p_rl = 0;        /* help window is left-to-right */
  2749. #endif
  2750. #ifdef FEAT_FOLDING
  2751.     curwin->w_p_fen = FALSE;    /* No folding in the help window */
  2752. #endif
  2753. #ifdef FEAT_DIFF
  2754.     curwin->w_p_diff = FALSE;    /* No 'diff' */
  2755. #endif
  2756.  
  2757. #ifdef FEAT_AUTOCMD
  2758.     buf = curbuf;
  2759. #endif
  2760.     set_buflisted(FALSE);
  2761.     }
  2762.     else
  2763.     {
  2764. #ifdef FEAT_AUTOCMD
  2765.     buf = curbuf;
  2766. #endif
  2767.     set_buflisted(TRUE);
  2768.     }
  2769.  
  2770. #ifdef FEAT_AUTOCMD
  2771.     /* If autocommands change buffers under our fingers, forget about
  2772.      * editing the file. */
  2773.     if (buf != curbuf)
  2774.     goto theend;
  2775.  
  2776.     /* Since we are starting to edit a file, consider the filetype to be
  2777.      * unset.  Helps for when an autocommand changes files and expects syntax
  2778.      * highlighting to work in the other file. */
  2779.     did_filetype = FALSE;
  2780. #endif
  2781.  
  2782. /*
  2783.  * other_file    oldbuf
  2784.  *  FALSE    FALSE        re-edit same file, buffer is re-used
  2785.  *  FALSE    TRUE        re-edit same file, nothing changes
  2786.  *  TRUE    FALSE        start editing new file, new buffer
  2787.  *  TRUE    TRUE        start editing in existing buffer (nothing to do)
  2788.  */
  2789.     if (!other_file && !oldbuf)        /* re-use the buffer */
  2790.     {
  2791.     set_last_cursor(curwin);    /* may set b_last_cursor */
  2792.     if (newlnum == ECMD_LAST || newlnum == ECMD_LASTL)
  2793.     {
  2794.         newlnum = curwin->w_cursor.lnum;
  2795.         solcol = curwin->w_cursor.col;
  2796.     }
  2797. #ifdef FEAT_AUTOCMD
  2798.     buf = curbuf;
  2799.     if (buf->b_fname != NULL)
  2800.         new_name = vim_strsave(buf->b_fname);
  2801.     else
  2802.         new_name = NULL;
  2803. #endif
  2804.     buf_freeall(curbuf, FALSE);    /* free all things for buffer */
  2805. #ifdef FEAT_AUTOCMD
  2806.     /* If autocommands deleted the buffer we were going to re-edit, give
  2807.      * up and jump to the end. */
  2808.     if (!buf_valid(buf))
  2809.     {
  2810.         delbuf_msg(new_name);    /* frees new_name */
  2811.         goto theend;
  2812.     }
  2813.     vim_free(new_name);
  2814.  
  2815.     /* If autocommands change buffers under our fingers, forget about
  2816.      * re-editing the file.  Should do the buf_clear_file(), but perhaps
  2817.      * the autocommands changed the buffer... */
  2818.     if (buf != curbuf)
  2819.         goto theend;
  2820. #endif
  2821.     buf_clear_file(curbuf);
  2822.     curbuf->b_op_start.lnum = 0;    /* clear '[ and '] marks */
  2823.     curbuf->b_op_end.lnum = 0;
  2824.     }
  2825.  
  2826. /*
  2827.  * If we get here we are sure to start editing
  2828.  */
  2829.     /* don't redraw until the cursor is in the right line */
  2830.     ++RedrawingDisabled;
  2831.  
  2832.     /* Assume success now */
  2833.     retval = OK;
  2834.  
  2835.     /*
  2836.      * Reset cursor position, could be used by autocommands.
  2837.      */
  2838.     check_cursor();
  2839.  
  2840.     /*
  2841.      * Check if we are editing the w_arg_idx file in the argument list.
  2842.      */
  2843.     check_arg_idx(curwin);
  2844.  
  2845. #ifdef FEAT_AUTOCMD
  2846.     if (!auto_buf)
  2847. #endif
  2848.     {
  2849.     /*
  2850.      * Set cursor and init window before reading the file and executing
  2851.      * autocommands.  This allows for the autocommands to position the
  2852.      * cursor.
  2853.      */
  2854.     win_init(curwin);
  2855.  
  2856. #ifdef FEAT_FOLDING
  2857.     /* It's like all lines in the buffer changed.  Need to update
  2858.      * automatic folding. */
  2859.     foldUpdateAll(curwin);
  2860. #endif
  2861.  
  2862. #ifdef FEAT_SUN_WORKSHOP
  2863.     if (usingSunWorkShop && curbuf->b_ffname != NULL
  2864.                      && vim_chdirfile(curbuf->b_ffname) == OK)
  2865.         shorten_fnames(TRUE);
  2866. #endif
  2867.     /*
  2868.      * Careful: open_buffer() and apply_autocmds() may change the current
  2869.      * buffer and window.
  2870.      */
  2871.     lnum = curwin->w_cursor.lnum;
  2872.     topline = curwin->w_topline;
  2873.     if (!oldbuf)                /* need to read the file */
  2874.     {
  2875. #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
  2876.         swap_exists_action = SEA_DIALOG;
  2877. #endif
  2878.         curbuf->b_flags |= BF_CHECK_RO; /* set/reset 'ro' flag */
  2879.  
  2880.         /*
  2881.          * Open the buffer and read the file.
  2882.          */
  2883.         (void)open_buffer(FALSE, eap);
  2884.  
  2885. #if defined(FEAT_GUI_DIALOG) || defined(FEAT_CON_DIALOG)
  2886.         if (swap_exists_action == SEA_QUIT)
  2887.         retval = FAIL;
  2888.         handle_swap_exists(old_curbuf);
  2889. #endif
  2890.     }
  2891. #ifdef FEAT_AUTOCMD
  2892.     else
  2893.     {
  2894.         apply_autocmds(EVENT_BUFENTER, NULL, NULL, FALSE, curbuf);
  2895.         apply_autocmds(EVENT_BUFWINENTER, NULL, NULL, FALSE, curbuf);
  2896.     }
  2897.     check_arg_idx(curwin);
  2898. #endif
  2899.  
  2900.     /*
  2901.      * If autocommands change the cursor position or topline, we should
  2902.      * keep it.
  2903.      */
  2904.     if (curwin->w_cursor.lnum != lnum)
  2905.     {
  2906.         newlnum = curwin->w_cursor.lnum;
  2907.         newcol = curwin->w_cursor.col;
  2908.     }
  2909.     if (curwin->w_topline == topline)
  2910.         topline = 0;
  2911.  
  2912.     /* Even when cursor didn't move we need to recompute topline. */
  2913.     changed_line_abv_curs();
  2914.  
  2915. #ifdef FEAT_TITLE
  2916.     maketitle();
  2917. #endif
  2918.     }
  2919.  
  2920. #ifdef FEAT_DIFF
  2921.     /* Tell the diff stuff that this buffer is new and/or needs updating.
  2922.      * Also needed when re-editing the same buffer, because unloading will
  2923.      * have removed it as a diff buffer. */
  2924.     diff_new_buffer();
  2925.     diff_invalidate();
  2926. #endif
  2927.  
  2928.     if (command == NULL)
  2929.     {
  2930.     if (newcol >= 0)    /* position set by autocommands */
  2931.     {
  2932.         curwin->w_cursor.lnum = newlnum;
  2933.         curwin->w_cursor.col = newcol;
  2934.         check_cursor();
  2935.     }
  2936.     else if (newlnum > 0)    /* line number from caller or old position */
  2937.     {
  2938.         curwin->w_cursor.lnum = newlnum;
  2939.         check_cursor_lnum();
  2940.         if (solcol >= 0 && !p_sol)
  2941.         {
  2942.         /* 'sol' is off: Use last known column. */
  2943.         curwin->w_cursor.col = solcol;
  2944.         check_cursor_col();
  2945. #ifdef FEAT_VIRTUALEDIT
  2946.         curwin->w_cursor.coladd = 0;
  2947. #endif
  2948.         curwin->w_set_curswant = TRUE;
  2949.         }
  2950.         else
  2951.         beginline(BL_SOL | BL_FIX);
  2952.     }
  2953.     else            /* no line number, go to last line in Ex mode */
  2954.     {
  2955.         if (exmode_active)
  2956.         curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
  2957.         beginline(BL_WHITE | BL_FIX);
  2958.     }
  2959.     }
  2960.  
  2961. #ifdef FEAT_WINDOWS
  2962.     /* Check if cursors in other windows on the same buffer are still valid */
  2963.     check_lnums(FALSE);
  2964. #endif
  2965.  
  2966.     /*
  2967.      * Did not read the file, need to show some info about the file.
  2968.      * Do this after setting the cursor.
  2969.      */
  2970.     if (oldbuf
  2971. #ifdef FEAT_AUTOCMD
  2972.         && !auto_buf
  2973. #endif
  2974.                 )
  2975.     fileinfo(FALSE, TRUE, FALSE);
  2976.  
  2977.     if (command != NULL)
  2978.     do_cmdline(command, NULL, NULL, DOCMD_VERBOSE);
  2979.  
  2980. #ifdef FEAT_KEYMAP
  2981.     if (curbuf->b_kmap_state & KEYMAP_INIT)
  2982.     keymap_init();
  2983. #endif
  2984.  
  2985.     --RedrawingDisabled;
  2986.     if (!skip_redraw)
  2987.     {
  2988.     n = p_so;
  2989.     if (topline == 0 && command == NULL)
  2990.         p_so = 999;            /* force cursor halfway the window */
  2991.     update_topline();
  2992. #ifdef FEAT_SCROLLBIND
  2993.     curwin->w_scbind_pos = curwin->w_topline;
  2994. #endif
  2995.     p_so = n;
  2996.     redraw_curbuf_later(NOT_VALID);    /* redraw this buffer later */
  2997.     }
  2998.  
  2999.     if (p_im)
  3000.     need_start_insertmode = TRUE;
  3001.  
  3002. #ifdef FEAT_SUN_WORKSHOP
  3003.     if (usingSunWorkShop && curbuf->b_ffname != NULL
  3004.                      && vim_chdirfile(curbuf->b_ffname) == OK)
  3005.     shorten_fnames(TRUE);
  3006.  
  3007.     if (gui.in_use && curbuf != NULL && curbuf->b_fname != NULL)
  3008.     workshop_file_opened((char *)curbuf->b_ffname, curbuf->b_p_ro);
  3009. #endif
  3010.  
  3011. theend:
  3012. #ifdef FEAT_BROWSE
  3013.     vim_free(browse_file);
  3014. #endif
  3015.     vim_free(free_fname);
  3016.     return retval;
  3017. }
  3018.  
  3019. #ifdef FEAT_AUTOCMD
  3020.     static void
  3021. delbuf_msg(name)
  3022.     char_u    *name;
  3023. {
  3024.     EMSG2(_("E143: Autocommands unexpectedly deleted new buffer %s"),
  3025.         name == NULL ? (char_u *)"" : name);
  3026.     vim_free(name);
  3027.     au_new_curbuf = NULL;
  3028. }
  3029. #endif
  3030.  
  3031. /*
  3032.  * ":insert" and ":append", also used by ":change"
  3033.  */
  3034.     void
  3035. ex_append(eap)
  3036.     exarg_T    *eap;
  3037. {
  3038.     char_u    *theline;
  3039.     int        did_undo = FALSE;
  3040.     linenr_T    lnum = eap->line2;
  3041.  
  3042.     if (eap->cmdidx != CMD_append)
  3043.     --lnum;
  3044.  
  3045.     State = INSERT;            /* behave like in Insert mode */
  3046.     if (curbuf->b_p_iminsert == B_IMODE_LMAP)
  3047.     State |= LANGMAP;
  3048.     while (1)
  3049.     {
  3050.     msg_scroll = TRUE;
  3051.     need_wait_return = FALSE;
  3052.     if (eap->getline == NULL)
  3053.         theline = getcmdline(
  3054. #ifdef FEAT_EVAL
  3055.             eap->cstack->cs_whilelevel > 0 ? -1 :
  3056. #endif
  3057.             NUL, 0L, 0);
  3058.     else
  3059.         theline = eap->getline(
  3060. #ifdef FEAT_EVAL
  3061.             eap->cstack->cs_whilelevel > 0 ? -1 :
  3062. #endif
  3063.             NUL, eap->cookie, 0);
  3064.     lines_left = Rows - 1;
  3065.     if (theline == NULL || (theline[0] == '.' && theline[1] == NUL))
  3066.         break;
  3067.  
  3068.     if (!did_undo && u_save(lnum, lnum + 1) == FAIL)
  3069.         break;
  3070.     did_undo = TRUE;
  3071.     ml_append(lnum, theline, (colnr_T)0, FALSE);
  3072.     appended_lines_mark(lnum, 1L);
  3073.  
  3074.     vim_free(theline);
  3075.     ++lnum;
  3076.     msg_didout = TRUE;    /* also scroll for empty line */
  3077.     }
  3078.     State = NORMAL;
  3079.  
  3080.     /* "start" is set to eap->line2+1 unless that position is invalid (when
  3081.      * eap->line2 pointed to the end of the buffer and nothig was appended)
  3082.      * "end" is set to lnum when something has been appended, otherwise
  3083.      * it is the same than "start"  -- Acevedo */
  3084.     curbuf->b_op_start.lnum = (eap->line2 < curbuf->b_ml.ml_line_count) ?
  3085.     eap->line2 + 1 : curbuf->b_ml.ml_line_count;
  3086.     if (eap->cmdidx != CMD_append)
  3087.     --curbuf->b_op_start.lnum;
  3088.     curbuf->b_op_end.lnum = (eap->line2 < lnum)
  3089.                          ? lnum : curbuf->b_op_start.lnum;
  3090.     curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
  3091.     curwin->w_cursor.lnum = lnum;
  3092.     check_cursor_lnum();
  3093.     beginline(BL_SOL | BL_FIX);
  3094.  
  3095.     need_wait_return = FALSE;    /* don't use wait_return() now */
  3096.     ex_no_reprint = TRUE;
  3097. }
  3098.  
  3099. /*
  3100.  * ":change"
  3101.  */
  3102.     void
  3103. ex_change(eap)
  3104.     exarg_T    *eap;
  3105. {
  3106.     linenr_T    lnum;
  3107.  
  3108.     if (eap->line2 >= eap->line1
  3109.         && u_save(eap->line1 - 1, eap->line2 + 1) == FAIL)
  3110.     return;
  3111.  
  3112.     for (lnum = eap->line2; lnum >= eap->line1; --lnum)
  3113.     {
  3114.     if (curbuf->b_ml.ml_flags & ML_EMPTY)        /* nothing to delete */
  3115.         break;
  3116.     ml_delete(eap->line1, FALSE);
  3117.     }
  3118.     deleted_lines_mark(eap->line1, (long)(eap->line2 - lnum));
  3119.  
  3120.     /* ":append" on the line above the deleted lines. */
  3121.     eap->line2 = eap->line1;
  3122.     ex_append(eap);
  3123. }
  3124.  
  3125.     void
  3126. ex_z(eap)
  3127.     exarg_T    *eap;
  3128. {
  3129.     char_u    *x;
  3130.     int        bigness = curwin->w_height - 3;
  3131.     char_u    kind;
  3132.     int        numbered = FALSE;
  3133.     int        minus = 0;
  3134.     linenr_T    start, end, curs, i;
  3135.     int        j;
  3136.     linenr_T    lnum = eap->line2;
  3137.  
  3138.     if (bigness < 1)
  3139.     bigness = 1;
  3140.  
  3141.     x = eap->arg;
  3142.     if (*x == '#')
  3143.     {
  3144.     numbered = TRUE;
  3145.     ++x;
  3146.     }
  3147.  
  3148.     kind = *x;
  3149.     if (kind == '-' || kind == '+' || kind == '=' || kind == '^' || kind == '.')
  3150.     ++x;
  3151.  
  3152.     if (*x != 0)
  3153.     {
  3154.     if (!isdigit(*x))
  3155.     {
  3156.         EMSG(_("E144: non-numeric argument to :z"));
  3157.         return;
  3158.     }
  3159.     else
  3160.         bigness = atoi((char *)x);
  3161.     }
  3162.  
  3163.     switch (kind)
  3164.     {
  3165.     case '-':
  3166.         start = lnum - bigness;
  3167.         end = lnum;
  3168.         curs = lnum;
  3169.         break;
  3170.  
  3171.     case '=':
  3172.         start = lnum - bigness / 2 + 1;
  3173.         end = lnum + bigness / 2 - 1;
  3174.         curs = lnum;
  3175.         minus = 1;
  3176.         break;
  3177.  
  3178.     case '^':
  3179.         start = lnum - bigness * 2;
  3180.         end = lnum - bigness;
  3181.         curs = lnum - bigness;
  3182.         break;
  3183.  
  3184.     case '.':
  3185.         start = lnum - bigness / 2;
  3186.         end = lnum + bigness / 2;
  3187.         curs = end;
  3188.         break;
  3189.  
  3190.     default:  /* '+' */
  3191.         start = lnum;
  3192.         end = lnum + bigness;
  3193.         curs = end;
  3194.         break;
  3195.     }
  3196.  
  3197.     if (start < 1)
  3198.     start = 1;
  3199.  
  3200.     if (end > curbuf->b_ml.ml_line_count)
  3201.     end = curbuf->b_ml.ml_line_count;
  3202.  
  3203.     if (curs > curbuf->b_ml.ml_line_count)
  3204.     curs = curbuf->b_ml.ml_line_count;
  3205.  
  3206.     for (i = start; i <= end; i++)
  3207.     {
  3208.     if (minus && i == lnum)
  3209.     {
  3210.         msg_putchar('\n');
  3211.  
  3212.         for (j = 1; j < Columns; j++)
  3213.         msg_putchar('-');
  3214.     }
  3215.  
  3216.     print_line(i, numbered);
  3217.  
  3218.     if (minus && i == lnum)
  3219.     {
  3220.         msg_putchar('\n');
  3221.  
  3222.         for (j = 1; j < Columns; j++)
  3223.         msg_putchar('-');
  3224.     }
  3225.     }
  3226.  
  3227.     curwin->w_cursor.lnum = curs;
  3228.     ex_no_reprint = TRUE;
  3229. }
  3230.  
  3231. /*
  3232.  * Check if the restricted flag is set.
  3233.  * If so, give an error message and return TRUE.
  3234.  * Otherwise, return FALSE.
  3235.  */
  3236.     int
  3237. check_restricted()
  3238. {
  3239.     if (restricted)
  3240.     {
  3241.     EMSG(_("E145: Shell commands not allowed in rvim"));
  3242.     return TRUE;
  3243.     }
  3244.     return FALSE;
  3245. }
  3246.  
  3247. /*
  3248.  * Check if the secure flag is set (.exrc or .vimrc in current directory).
  3249.  * If so, give an error message and return TRUE.
  3250.  * Otherwise, return FALSE.
  3251.  */
  3252.     int
  3253. check_secure()
  3254. {
  3255.     if (secure)
  3256.     {
  3257.     secure = 2;
  3258.     EMSG(_(e_curdir));
  3259.     return TRUE;
  3260.     }
  3261. #ifdef HAVE_SANDBOX
  3262.     /*
  3263.      * In the sandbox more things are not allowed, including the things
  3264.      * disallowed in secure mode.
  3265.      */
  3266.     if (sandbox != 0)
  3267.     {
  3268.     EMSG(_(e_sandbox));
  3269.     return TRUE;
  3270.     }
  3271. #endif
  3272.     return FALSE;
  3273. }
  3274.  
  3275. static char_u    *old_sub = NULL;    /* previous substitute pattern */
  3276. static int    global_need_beginline;    /* call beginline() after ":g" */
  3277.  
  3278. /*
  3279.  * When ":global" is used to number of substitutions and changed lines is
  3280.  * accumulated until it's finished.
  3281.  */
  3282. static long    sub_nsubs;    /* total number of substitutions */
  3283. static linenr_T    sub_nlines;    /* total number of lines changed */
  3284.  
  3285. /* do_sub()
  3286.  *
  3287.  * Perform a substitution from line eap->line1 to line eap->line2 using the
  3288.  * command pointed to by eap->arg which should be of the form:
  3289.  *
  3290.  * /pattern/substitution/{flags}
  3291.  *
  3292.  * The usual escapes are supported as described in the regexp docs.
  3293.  */
  3294.     void
  3295. do_sub(eap)
  3296.     exarg_T    *eap;
  3297. {
  3298.     linenr_T    lnum;
  3299.     long    i = 0;
  3300.     regmmatch_T regmatch;
  3301.     static int    do_all = FALSE;        /* do multiple substitutions per line */
  3302.     static int    do_ask = FALSE;        /* ask for confirmation */
  3303.     static int    do_error = TRUE;    /* if false, ignore errors */
  3304.     static int    do_print = FALSE;    /* print last line with subs. */
  3305.     static int    do_ic = 0;        /* ignore case flag */
  3306.     char_u    *pat = NULL, *sub = NULL;    /* init for GCC */
  3307.     int        delimiter;
  3308.     int        sublen;
  3309.     int        got_quit = FALSE;
  3310.     int        got_match = FALSE;
  3311.     int        temp;
  3312.     int        which_pat;
  3313.     char_u    *cmd;
  3314.     int        save_State;
  3315.     linenr_T    first_line = 0;    /* first changed line */
  3316.     linenr_T    last_line= 0;    /* below last changed line AFTER the
  3317.                      * change */
  3318.     linenr_T    old_line_count = curbuf->b_ml.ml_line_count;
  3319.     linenr_T    line2;
  3320.     long    nmatch;        /* number of lines in match */
  3321.     linenr_T    sub_firstlnum;    /* nr of first sub line */
  3322.     char_u    *sub_firstline;    /* allocated copy of first sub line */
  3323.  
  3324.     cmd = eap->arg;
  3325.     if (!global_busy)
  3326.     {
  3327.     sub_nsubs = 0;
  3328.     sub_nlines = 0;
  3329.     }
  3330.  
  3331. #ifdef FEAT_FKMAP    /* reverse the flow of the Farsi characters */
  3332.     if (p_altkeymap && curwin->w_p_rl)
  3333.     lrF_sub(cmd);
  3334. #endif
  3335.  
  3336.     if (eap->cmdidx == CMD_tilde)
  3337.     which_pat = RE_LAST;    /* use last used regexp */
  3338.     else
  3339.     which_pat = RE_SUBST;    /* use last substitute regexp */
  3340.  
  3341.                 /* new pattern and substitution */
  3342.     if (eap->cmd[0] == 's' && *cmd != NUL && !vim_iswhite(*cmd)
  3343.         && vim_strchr((char_u *)"0123456789cegriIp|\"", *cmd) == NULL)
  3344.     {
  3345.                 /* don't accept alphanumeric for separator */
  3346.     if (isalpha(*cmd))
  3347.     {
  3348.         EMSG(_("E146: Regular expressions can't be delimited by letters"));
  3349.         return;
  3350.     }
  3351.     /*
  3352.      * undocumented vi feature:
  3353.      *  "\/sub/" and "\?sub?" use last used search pattern (almost like
  3354.      *  //sub/r).  "\&sub&" use last substitute pattern (like //sub/).
  3355.      */
  3356.     if (*cmd == '\\')
  3357.     {
  3358.         ++cmd;
  3359.         if (vim_strchr((char_u *)"/?&", *cmd) == NULL)
  3360.         {
  3361.         EMSG(_(e_backslash));
  3362.         return;
  3363.         }
  3364.         if (*cmd != '&')
  3365.         which_pat = RE_SEARCH;        /* use last '/' pattern */
  3366.         pat = (char_u *)"";            /* empty search pattern */
  3367.         delimiter = *cmd++;            /* remember delimiter character */
  3368.     }
  3369.     else        /* find the end of the regexp */
  3370.     {
  3371.         which_pat = RE_LAST;        /* use last used regexp */
  3372.         delimiter = *cmd++;            /* remember delimiter character */
  3373.         pat = cmd;                /* remember start of search pat */
  3374.         cmd = skip_regexp(cmd, delimiter, p_magic);
  3375.         if (cmd[0] == delimiter)        /* end delimiter found */
  3376.         *cmd++ = NUL;            /* replace it with a NUL */
  3377.     }
  3378.  
  3379.     /*
  3380.      * Small incompatibility: vi sees '\n' as end of the command, but in
  3381.      * Vim we want to use '\n' to find/substitute a NUL.
  3382.      */
  3383.     sub = cmd;        /* remember the start of the substitution */
  3384.  
  3385.     while (cmd[0])
  3386.     {
  3387.         if (cmd[0] == delimiter)        /* end delimiter found */
  3388.         {
  3389.         *cmd++ = NUL;            /* replace it with a NUL */
  3390.         break;
  3391.         }
  3392.         if (cmd[0] == '\\' && cmd[1] != 0)    /* skip escaped characters */
  3393.         ++cmd;
  3394. #ifdef FEAT_MBYTE
  3395.         if (has_mbyte)
  3396.         cmd += (*mb_ptr2len_check)(cmd);
  3397.         else
  3398. #endif
  3399.         ++cmd;
  3400.     }
  3401.  
  3402.     if (!eap->skip)
  3403.     {
  3404.         vim_free(old_sub);
  3405.         old_sub = vim_strsave(sub);
  3406.     }
  3407.     }
  3408.     else if (!eap->skip)    /* use previous pattern and substitution */
  3409.     {
  3410.     if (old_sub == NULL)    /* there is no previous command */
  3411.     {
  3412.         EMSG(_(e_nopresub));
  3413.         return;
  3414.     }
  3415.     pat = NULL;        /* search_regcomp() will use previous pattern */
  3416.     sub = old_sub;
  3417.     }
  3418.  
  3419.     /*
  3420.      * Find trailing options.  When '&' is used, keep old options.
  3421.      */
  3422.     if (*cmd == '&')
  3423.     ++cmd;
  3424.     else
  3425.     {
  3426.     if (!p_ed)
  3427.     {
  3428.         if (p_gd)        /* default is global on */
  3429.         do_all = TRUE;
  3430.         else
  3431.         do_all = FALSE;
  3432.         do_ask = FALSE;
  3433.     }
  3434.     do_error = TRUE;
  3435.     do_print = FALSE;
  3436.     do_ic = 0;
  3437.     }
  3438.     while (*cmd)
  3439.     {
  3440.     /*
  3441.      * Note that 'g' and 'c' are always inverted, also when p_ed is off.
  3442.      * 'r' is never inverted.
  3443.      */
  3444.     if (*cmd == 'g')
  3445.         do_all = !do_all;
  3446.     else if (*cmd == 'c')
  3447.         do_ask = !do_ask;
  3448.     else if (*cmd == 'e')
  3449.         do_error = !do_error;
  3450.     else if (*cmd == 'r')        /* use last used regexp */
  3451.         which_pat = RE_LAST;
  3452.     else if (*cmd == 'p')
  3453.         do_print = TRUE;
  3454.     else if (*cmd == 'i')        /* ignore case */
  3455.         do_ic = 'i';
  3456.     else if (*cmd == 'I')        /* don't ignore case */
  3457.         do_ic = 'I';
  3458.     else
  3459.         break;
  3460.     ++cmd;
  3461.     }
  3462.  
  3463.     /*
  3464.      * check for a trailing count
  3465.      */
  3466.     cmd = skipwhite(cmd);
  3467.     if (isdigit(*cmd))
  3468.     {
  3469.     i = getdigits(&cmd);
  3470.     if (i <= 0 && !eap->skip && do_error)
  3471.     {
  3472.         EMSG(_(e_zerocount));
  3473.         return;
  3474.     }
  3475.     eap->line1 = eap->line2;
  3476.     eap->line2 += i - 1;
  3477.     }
  3478.  
  3479.     /*
  3480.      * check for trailing command or garbage
  3481.      */
  3482.     cmd = skipwhite(cmd);
  3483.     if (*cmd && *cmd != '"')        /* if not end-of-line or comment */
  3484.     {
  3485.     eap->nextcmd = check_nextcmd(cmd);
  3486.     if (eap->nextcmd == NULL)
  3487.     {
  3488.         EMSG(_(e_trailing));
  3489.         return;
  3490.     }
  3491.     }
  3492.  
  3493.     if (eap->skip)        /* not executing commands, only parsing */
  3494.     return;
  3495.  
  3496.     if (search_regcomp(pat, RE_SUBST, which_pat, SEARCH_HIS, ®match) == FAIL)
  3497.     {
  3498.     if (do_error)
  3499.         EMSG(_(e_invcmd));
  3500.     return;
  3501.     }
  3502.  
  3503.     /* the 'i' or 'I' flag overrules 'ignorecase' and 'smartcase' */
  3504.     if (do_ic == 'i')
  3505.     regmatch.rmm_ic = TRUE;
  3506.     else if (do_ic == 'I')
  3507.     regmatch.rmm_ic = FALSE;
  3508.  
  3509.     sub_firstline = NULL;
  3510.  
  3511.     /*
  3512.      * ~ in the substitute pattern is replaced with the old pattern.
  3513.      * We do it here once to avoid it to be replaced over and over again.
  3514.      */
  3515.     sub = regtilde(sub, p_magic);
  3516.  
  3517.     /*
  3518.      * Check for a match on each line.
  3519.      */
  3520.     line2 = eap->line2;
  3521.     for (lnum = eap->line1; lnum <= line2 && !(got_int || got_quit); ++lnum)
  3522.     {
  3523.     sub_firstlnum = lnum;
  3524.     nmatch = vim_regexec_multi(®match, curwin, curbuf, lnum, (colnr_T)0);
  3525.     if (nmatch)
  3526.     {
  3527.         colnr_T    copycol;
  3528.         colnr_T    matchcol;
  3529.         colnr_T    prev_matchcol = MAXCOL;
  3530.         char_u    *new_end, *new_start = NULL;
  3531.         unsigned    new_start_len = 0;
  3532.         char_u    *p1;
  3533.         int        did_sub = FALSE;
  3534.         int        lastone;
  3535.         unsigned    len, needed_len;
  3536.         long    nmatch_tl = 0;    /* nr of lines matched below lnum */
  3537.         int        do_again;    /* do it again after joining lines */
  3538.  
  3539.         /*
  3540.          * The new text is build up step by step, to avoid too much
  3541.          * copying.  There are these pieces:
  3542.          * sub_firstline    The old text, unmodifed.
  3543.          * copycol        Column in the old text where we started
  3544.          *            looking for a match; from here old text still
  3545.          *            needs to be copied to the new text.
  3546.          * matchcol        Column number of the old text where to look
  3547.          *            for the next match.  It's just after the
  3548.          *            previous match or one further.
  3549.          * prev_matchcol    Column just after the previous match (if any).
  3550.          *            Mostly equal to matchcol, except for the first
  3551.          *            match and after skipping an empty match.
  3552.          * regmatch.*pos    Where the pattern matched in the old text.
  3553.          * new_start    The new text, all that has been produced so
  3554.          *            far.
  3555.          * new_end        The new text, where to append new text.
  3556.          *
  3557.          * lnum        The line number where we were looking for the
  3558.          *            first match in the old line.
  3559.          * sub_firstlnum    The line number in the buffer where to look
  3560.          *            for a match.  Can be different from "lnum"
  3561.          *            when the pattern or substitute string contains
  3562.          *            line breaks.
  3563.          *
  3564.          * Special situations:
  3565.          * - When the substitute string contains a line break, the part up
  3566.          *   to the line break is inserted in the text, but the copy of
  3567.          *   the original line is kept.  "sub_firstlnum" is adjusted for
  3568.          *   the inserted lines.
  3569.          * - When the matched pattern contains a line break, the old line
  3570.          *   is taken from the line at the end of the pattern.  The lines
  3571.          *   in the match are deleted later, "sub_firstlnum" is adjusted
  3572.          *   accordingly.
  3573.          *
  3574.          * The new text is built up in new_start[].  It has some extra
  3575.          * room to avoid using alloc()/free() too often.  new_start_len is
  3576.          * the lenght of the allocated memory at new_start.
  3577.          *
  3578.          * Make a copy of the old line, so it won't be taken away when
  3579.          * updating the screen or handling a multi-line match.  The "old_"
  3580.          * pointers point into this copy.
  3581.          */
  3582.         sub_firstline = vim_strsave(ml_get(sub_firstlnum));
  3583.         if (sub_firstline == NULL)
  3584.         {
  3585.         vim_free(new_start);
  3586.         goto outofmem;
  3587.         }
  3588.         copycol = 0;
  3589.         matchcol = 0;
  3590.  
  3591.         /* At first match, remember current cursor position. */
  3592.         if (!got_match)
  3593.         {
  3594.         setpcmark();
  3595.         got_match = TRUE;
  3596.         }
  3597.  
  3598.         /*
  3599.          * Loop until nothing more to replace in this line.
  3600.          * 1. Handle match with empty string.
  3601.          * 2. If do_ask is set, ask for confirmation.
  3602.          * 3. substitute the string.
  3603.          * 4. if do_all is set, find next match
  3604.          * 5. break if there isn't another match in this line
  3605.          */
  3606.         for (;;)
  3607.         {
  3608.         /* Save the line number of the last change for the final
  3609.          * cursor position (just like Vi). */
  3610.         curwin->w_cursor.lnum = lnum;
  3611.         do_again = FALSE;
  3612.  
  3613.         /*
  3614.          * 1. Match empty string does not count, except for first
  3615.          * match.  This reproduces the strange vi behaviour.
  3616.          * This also catches endless loops.
  3617.          */
  3618.         if (matchcol == prev_matchcol
  3619.             && regmatch.endpos[0].lnum == 0
  3620.             && matchcol == regmatch.endpos[0].col)
  3621.         {
  3622.             ++matchcol; /* search for a match at next column */
  3623.             goto skip;
  3624.         }
  3625.  
  3626.         /* Normally we continue searching for a match just after the
  3627.          * previous match. */
  3628.         matchcol = regmatch.endpos[0].col;
  3629.         prev_matchcol = matchcol;
  3630.  
  3631.         /*
  3632.          * 2. If do_ask is set, ask for confirmation.
  3633.          */
  3634.         if (do_ask)
  3635.         {
  3636.             /* change State to CONFIRM, so that the mouse works
  3637.              * properly */
  3638.             save_State = State;
  3639.             State = CONFIRM;
  3640. #ifdef FEAT_MOUSE
  3641.             setmouse();        /* disable mouse in xterm */
  3642. #endif
  3643.             curwin->w_cursor.col = regmatch.startpos[0].col;
  3644.  
  3645.             /* When 'cpoptions' contains "u" don't sync undo when
  3646.              * asking for confirmation. */
  3647.             if (vim_strchr(p_cpo, CPO_UNDO) != NULL)
  3648.             ++no_u_sync;
  3649.  
  3650.             /*
  3651.              * Loop until 'y', 'n', 'q', CTRL-E or CTRL-Y typed.
  3652.              */
  3653.             while (do_ask)
  3654.             {
  3655. #ifdef FEAT_FOLDING
  3656.             int save_p_fen = curwin->w_p_fen;
  3657.  
  3658.             curwin->w_p_fen = FALSE;
  3659. #endif
  3660.             /* Invert the matched string.
  3661.              * Remove the inversion afterwards. */
  3662.             temp = RedrawingDisabled;
  3663.             RedrawingDisabled = 0;
  3664.  
  3665.             search_match_lines = regmatch.endpos[0].lnum;
  3666.             search_match_endcol = regmatch.endpos[0].col;
  3667.             highlight_match = TRUE;
  3668.  
  3669.             update_topline();
  3670.             validate_cursor();
  3671.             update_screen(NOT_VALID);
  3672.             highlight_match = FALSE;
  3673.             redraw_later(NOT_VALID);
  3674.  
  3675. #ifdef FEAT_FOLDING
  3676.             curwin->w_p_fen = save_p_fen;
  3677. #endif
  3678.             if (msg_row == Rows - 1)
  3679.                 msg_didout = FALSE;        /* avoid a scroll-up */
  3680.             msg_starthere();
  3681.             i = msg_scroll;
  3682.             msg_scroll = 0;        /* truncate msg when needed */
  3683.             msg_no_more = TRUE;
  3684.             /* write message same highlighting as for wait_return */
  3685.             smsg_attr(hl_attr(HLF_R),
  3686.                 (char_u *)_("replace with %s (y/n/a/q/l/^E/^Y)?"),
  3687.                 sub);
  3688.             msg_no_more = FALSE;
  3689.             msg_scroll = i;
  3690.             showruler(TRUE);
  3691.             windgoto(msg_row, msg_col);
  3692.             RedrawingDisabled = temp;
  3693.  
  3694. #ifdef USE_ON_FLY_SCROLL
  3695.             dont_scroll = FALSE;    /* allow scrolling here */
  3696. #endif
  3697.             ++no_mapping;        /* don't map this key */
  3698.             ++allow_keys;        /* allow special keys */
  3699.             i = safe_vgetc();
  3700.             --allow_keys;
  3701.             --no_mapping;
  3702.  
  3703.             /* clear the question */
  3704.             msg_didout = FALSE;    /* don't scroll up */
  3705.             msg_col = 0;
  3706.             gotocmdline(TRUE);
  3707.             need_wait_return = FALSE; /* no hit-return prompt */
  3708.             if (i == 'q' || i == ESC || i == Ctrl_C
  3709. #ifdef UNIX
  3710.                 || i == intr_char
  3711. #endif
  3712.                 )
  3713.             {
  3714.                 got_quit = TRUE;
  3715.                 break;
  3716.             }
  3717.             if (i == 'n')
  3718.                 break;
  3719.             if (i == 'y')
  3720.                 break;
  3721.             if (i == 'l')
  3722.             {
  3723.                 /* last: replace and then stop */
  3724.                 do_all = FALSE;
  3725.                 line2 = lnum;
  3726.                 break;
  3727.             }
  3728.             if (i == 'a')
  3729.             {
  3730.                 do_ask = FALSE;
  3731.                 break;
  3732.             }
  3733. #ifdef FEAT_INS_EXPAND
  3734.             if (i == Ctrl_E)
  3735.                 scrollup_clamp();
  3736.             else if (i == Ctrl_Y)
  3737.                 scrolldown_clamp();
  3738. #endif
  3739.             }
  3740.             State = save_State;
  3741. #ifdef FEAT_MOUSE
  3742.             setmouse();
  3743. #endif
  3744.             if (vim_strchr(p_cpo, CPO_UNDO) != NULL)
  3745.             --no_u_sync;
  3746.  
  3747.             if (i == 'n')
  3748.             {
  3749.             /* For a multi-line match, put matchcol at the NUL at
  3750.              * the end of the line, so that we continue looking
  3751.              * for a match on the next line.  Avoids that
  3752.              * ":s/\n//gc" get stuck. */
  3753.             if (nmatch > 1)
  3754.                 matchcol = STRLEN(sub_firstline);
  3755.             goto skip;
  3756.             }
  3757.             if (got_quit)
  3758.             break;
  3759.         }
  3760.  
  3761.         /* Move the cursor to the start of the line, to avoid that it
  3762.          * is beyond the end of the line after the substitution. */
  3763.         curwin->w_cursor.col = 0;
  3764.  
  3765.         /*
  3766.          * 3. substitute the string.
  3767.          */
  3768.         /* get length of substitution part */
  3769.         sublen = vim_regsub_multi(®match, sub_firstlnum,
  3770.                     sub, sub_firstline, FALSE, p_magic, TRUE);
  3771.  
  3772.         /* Need room for:
  3773.          * - result so far in new_start (not for first sub in line)
  3774.          * - original text up to match
  3775.          * - length of substituted part
  3776.          * - original text after match
  3777.          */
  3778.         if (nmatch == 1)
  3779.             p1 = sub_firstline;
  3780.         else
  3781.         {
  3782.             p1 = ml_get(sub_firstlnum + nmatch - 1);
  3783.             nmatch_tl += nmatch - 1;
  3784.         }
  3785.         i = regmatch.startpos[0].col - copycol;
  3786.         needed_len = i + ((unsigned)STRLEN(p1) - regmatch.endpos[0].col)
  3787.                                  + sublen + 1;
  3788.         if (new_start == NULL)
  3789.         {
  3790.             /*
  3791.              * Get some space for a temporary buffer to do the
  3792.              * substitution into (and some extra space to avoid
  3793.              * too many calls to alloc()/free()).
  3794.              */
  3795.             new_start_len = needed_len + 50;
  3796.             if ((new_start = alloc_check(new_start_len)) == NULL)
  3797.             goto outofmem;
  3798.             *new_start = NUL;
  3799.             new_end = new_start;
  3800.         }
  3801.         else
  3802.         {
  3803.             /*
  3804.              * Check if the temporary buffer is long enough to do the
  3805.              * substitution into.  If not, make it larger (with a bit
  3806.              * extra to avoid too many calls to alloc()/free()).
  3807.              */
  3808.             len = (unsigned)STRLEN(new_start);
  3809.             needed_len += len;
  3810.             if (needed_len > new_start_len)
  3811.             {
  3812.             new_start_len = needed_len + 50;
  3813.             if ((p1 = alloc_check(new_start_len)) == NULL)
  3814.             {
  3815.                 vim_free(new_start);
  3816.                 goto outofmem;
  3817.             }
  3818.             mch_memmove(p1, new_start, (size_t)(len + 1));
  3819.             vim_free(new_start);
  3820.             new_start = p1;
  3821.             }
  3822.             new_end = new_start + len;
  3823.         }
  3824.  
  3825.         /*
  3826.          * copy the text up to the part that matched
  3827.          */
  3828.         mch_memmove(new_end, sub_firstline + copycol, (size_t)i);
  3829.         new_end += i;
  3830.  
  3831.         (void)vim_regsub_multi(®match, sub_firstlnum,
  3832.                        sub, new_end, TRUE, p_magic, TRUE);
  3833.         sub_nsubs++;
  3834.         did_sub = TRUE;
  3835.  
  3836.         /* For a multi-line match, make a copy of the last matched
  3837.          * line and continue in that one. */
  3838.         if (nmatch > 1)
  3839.         {
  3840.             sub_firstlnum += nmatch - 1;
  3841.             vim_free(sub_firstline);
  3842.             sub_firstline = vim_strsave(ml_get(sub_firstlnum));
  3843.             /* When going beyond the last line, stop substituting. */
  3844.             if (sub_firstlnum <= line2)
  3845.             do_again = TRUE;
  3846.             else
  3847.             do_all = FALSE;
  3848.         }
  3849.  
  3850.         /* Remember next character to be copied. */
  3851.         copycol = regmatch.endpos[0].col;
  3852.  
  3853.         /*
  3854.          * Now the trick is to replace CTRL-M chars with a real line
  3855.          * break.  This would make it impossible to insert a CTRL-M in
  3856.          * the text.  The line break can be avoided by preceding the
  3857.          * CTRL-M with a backslash.  To be able to insert a backslash,
  3858.          * they must be doubled in the string and are halved here.
  3859.          * That is Vi compatible.
  3860.          */
  3861.         for (p1 = new_end; *p1; ++p1)
  3862.         {
  3863.             if (p1[0] == '\\' && p1[1] != NUL)
  3864.             STRCPY(p1, p1 + 1);        /* remove backslash */
  3865.             else if (*p1 == CR)
  3866.             {
  3867.             if (u_inssub(lnum) == OK)   /* prepare for undo */
  3868.             {
  3869.                 *p1 = NUL;            /* truncate up to the CR */
  3870.                 ml_append(lnum - 1, new_start,
  3871.                     (colnr_T)(p1 - new_start + 1), FALSE);
  3872.                 mark_adjust(lnum + 1, (linenr_T)MAXLNUM, 1L, 0L);
  3873.                 if (do_ask)
  3874.                 appended_lines(lnum - 1, 1L);
  3875.                 else
  3876.                 {
  3877.                 if (first_line == 0)
  3878.                     first_line = lnum;
  3879.                 last_line = lnum + 1;
  3880.                 }
  3881.                 /* All line numbers increase. */
  3882.                 ++sub_firstlnum;
  3883.                 ++lnum;
  3884.                 ++line2;
  3885.                 /* move the cursor to the new line, like Vi */
  3886.                 ++curwin->w_cursor.lnum;
  3887.                 STRCPY(new_start, p1 + 1);    /* copy the rest */
  3888.                 p1 = new_start - 1;
  3889.             }
  3890.             }
  3891. #ifdef FEAT_MBYTE
  3892.             else if (has_mbyte)
  3893.             p1 += (*mb_ptr2len_check)(p1) - 1;
  3894. #endif
  3895.         }
  3896.  
  3897.         /*
  3898.          * 4. If do_all is set, find next match.
  3899.          * Prevent endless loop with patterns that match empty
  3900.          * strings, e.g. :s/$/pat/g or :s/[a-z]* /(&)/g.
  3901.          */
  3902. skip:
  3903.         nmatch = -1;
  3904.         lastone = (sub_firstline[matchcol] == NUL
  3905.                  || got_int || got_quit || !(do_all || do_again));
  3906.         if (lastone
  3907.             || do_ask
  3908.             || (nmatch = vim_regexec_multi(®match, curwin,
  3909.                        curbuf, sub_firstlnum, matchcol)) == 0)
  3910.         {
  3911.             if (new_start != NULL)
  3912.             {
  3913.             /*
  3914.              * Copy the rest of the line, that didn't match.
  3915.              * matchcol has to be adjusted, we use the end of the
  3916.              * line as reference, because the substitute may have
  3917.              * changed the number of characters.
  3918.              */
  3919.             STRCAT(new_start, sub_firstline + copycol);
  3920.             matchcol = (colnr_T)STRLEN(sub_firstline) - matchcol;
  3921.  
  3922.             if (u_savesub(lnum) != OK)
  3923.                 break;
  3924.             ml_replace(lnum, new_start, TRUE);
  3925.  
  3926.             if (nmatch_tl > 0)
  3927.             {
  3928.                 /*
  3929.                  * Matched lines have now been substituted and are
  3930.                  * useless, delete them.  The part after the match
  3931.                  * has been appended to new_start, we don't need
  3932.                  * it in the buffer.
  3933.                  */
  3934.                 ++lnum;
  3935.                 if (u_savedel(lnum, nmatch_tl) != OK)
  3936.                 break;
  3937.                 for (i = 0; i < nmatch_tl; ++i)
  3938.                 ml_delete(lnum, (int)FALSE);
  3939.                 mark_adjust(lnum, lnum + nmatch_tl - 1,
  3940.                            (long)MAXLNUM, -nmatch_tl);
  3941.                 if (do_ask)
  3942.                 deleted_lines(lnum, nmatch_tl);
  3943.                 --lnum;
  3944.                 line2 -= nmatch_tl; /* nr of lines decreases */
  3945.                 nmatch_tl = 0;
  3946.             }
  3947.  
  3948.             /* When asking, undo is saved each time, must also set
  3949.              * changed flag each time. */
  3950.             if (do_ask)
  3951.                 changed_bytes(lnum, 0);
  3952.             else
  3953.             {
  3954.                 if (first_line == 0)
  3955.                 first_line = lnum;
  3956.                 last_line = lnum + 1;
  3957.             }
  3958.  
  3959.             sub_firstlnum = lnum;
  3960.             vim_free(sub_firstline);    /* free the temp buffer */
  3961.             sub_firstline = new_start;
  3962.             new_start = NULL;
  3963.             matchcol = (colnr_T)STRLEN(sub_firstline) - matchcol;
  3964.             copycol = 0;
  3965.             }
  3966.             if (nmatch == -1 && !lastone)
  3967.             nmatch = vim_regexec_multi(®match, curwin, curbuf,
  3968.                              sub_firstlnum, matchcol);
  3969.  
  3970.             /*
  3971.              * 5. break if there isn't another match in this line
  3972.              */
  3973.             if (nmatch <= 0)
  3974.             break;
  3975.         }
  3976.  
  3977.         line_breakcheck();
  3978.         }
  3979.  
  3980.         if (did_sub)
  3981.         ++sub_nlines;
  3982.         vim_free(sub_firstline);    /* free the copy of the original line */
  3983.         sub_firstline = NULL;
  3984.     }
  3985.  
  3986.     line_breakcheck();
  3987.     }
  3988.  
  3989.     if (first_line != 0)
  3990.     {
  3991.     /* Need to subtract the number of added lines from "last_line" to get
  3992.      * the line number before the change (same as adding the number of
  3993.      * deleted lines). */
  3994.     i = curbuf->b_ml.ml_line_count - old_line_count;
  3995.     changed_lines(first_line, 0, last_line - i, i);
  3996.     }
  3997.  
  3998. outofmem:
  3999.     vim_free(sub_firstline); /* may have to free allocated copy of the line */
  4000.     if (sub_nsubs)
  4001.     {
  4002.     /* Set the '[ and '] marks. */
  4003.     curbuf->b_op_start.lnum = eap->line1;
  4004.     curbuf->b_op_end.lnum = line2;
  4005.     curbuf->b_op_start.col = curbuf->b_op_end.col = 0;
  4006.  
  4007.     if (!global_busy)
  4008.     {
  4009.         beginline(BL_WHITE | BL_FIX);
  4010.         if (!do_sub_msg() && do_ask)
  4011.         MSG("");
  4012.     }
  4013.     else
  4014.         global_need_beginline = TRUE;
  4015.     if (do_print)
  4016.         print_line(curwin->w_cursor.lnum, FALSE);
  4017.     }
  4018.     else if (!global_busy)
  4019.     {
  4020.     if (got_int)        /* interrupted */
  4021.         EMSG(_(e_interr));
  4022.     else if (got_match)    /* did find something but nothing substituted */
  4023.         MSG("");
  4024.     else if (do_error)    /* nothing found */
  4025.         EMSG2(_(e_patnotf2), get_search_pat());
  4026.     }
  4027.  
  4028.     vim_free(regmatch.regprog);
  4029. }
  4030.  
  4031. /*
  4032.  * Give message for number of substitutions.
  4033.  * Can also be used after a ":global" command.
  4034.  * Return TRUE if a message was given.
  4035.  */
  4036.     static int
  4037. do_sub_msg()
  4038. {
  4039.     /*
  4040.      * Only report substitutions when:
  4041.      * - more than 'report' substitutions
  4042.      * - command was typed by user, or number of changed lines > 'report'
  4043.      * - giving messages is not disabled by 'lazyredraw'
  4044.      */
  4045.     if (sub_nsubs > p_report
  4046.         && (KeyTyped || sub_nlines > 1 || p_report < 1)
  4047.         && messaging())
  4048.     {
  4049.     if (got_int)
  4050.         STRCPY(msg_buf, _("(Interrupted) "));
  4051.     else
  4052.         msg_buf[0] = NUL;
  4053.     if (sub_nsubs == 1)
  4054.         STRCAT(msg_buf, _("1 substitution"));
  4055.     else
  4056.         sprintf((char *)msg_buf + STRLEN(msg_buf), _("%ld substitutions"),
  4057.                                    sub_nsubs);
  4058.     if (sub_nlines == 1)
  4059.         STRCAT(msg_buf, _(" on 1 line"));
  4060.     else
  4061.         sprintf((char *)msg_buf + STRLEN(msg_buf), _(" on %ld lines"),
  4062.                                 (long)sub_nlines);
  4063.     if (msg(msg_buf))
  4064.     {
  4065.         /* save message to display it after redraw */
  4066.         set_keep_msg(msg_buf);
  4067.         keep_msg_attr = 0;
  4068.     }
  4069.     return TRUE;
  4070.     }
  4071.     if (got_int)
  4072.     {
  4073.     EMSG(_(e_interr));
  4074.     return TRUE;
  4075.     }
  4076.     return FALSE;
  4077. }
  4078.  
  4079. /*
  4080.  * Execute a global command of the form:
  4081.  *
  4082.  * g/pattern/X : execute X on all lines where pattern matches
  4083.  * v/pattern/X : execute X on all lines where pattern does not match
  4084.  *
  4085.  * where 'X' is an EX command
  4086.  *
  4087.  * The command character (as well as the trailing slash) is optional, and
  4088.  * is assumed to be 'p' if missing.
  4089.  *
  4090.  * This is implemented in two passes: first we scan the file for the pattern and
  4091.  * set a mark for each line that (not) matches. secondly we execute the command
  4092.  * for each line that has a mark. This is required because after deleting
  4093.  * lines we do not know where to search for the next match.
  4094.  */
  4095.     void
  4096. ex_global(eap)
  4097.     exarg_T    *eap;
  4098. {
  4099.     linenr_T    lnum;        /* line number according to old situation */
  4100.     int        ndone;
  4101.     int        type;        /* first char of cmd: 'v' or 'g' */
  4102.     char_u    *cmd;        /* command argument */
  4103.  
  4104.     char_u    delim;        /* delimiter, normally '/' */
  4105.     char_u    *pat;
  4106.     regmmatch_T    regmatch;
  4107.     int        match;
  4108.     int        which_pat;
  4109.  
  4110.     if (global_busy)
  4111.     {
  4112.     EMSG(_("E147: Cannot do :global recursive"));    /* will increment global_busy */
  4113.     return;
  4114.     }
  4115.  
  4116.     if (eap->forceit)            /* ":global!" is like ":vglobal" */
  4117.     type = 'v';
  4118.     else
  4119.     type = *eap->cmd;
  4120.     cmd = eap->arg;
  4121.     which_pat = RE_LAST;        /* default: use last used regexp */
  4122.     sub_nsubs = 0;
  4123.     sub_nlines = 0;
  4124.  
  4125.     /*
  4126.      * undocumented vi feature:
  4127.      *    "\/" and "\?": use previous search pattern.
  4128.      *         "\&": use previous substitute pattern.
  4129.      */
  4130.     if (*cmd == '\\')
  4131.     {
  4132.     ++cmd;
  4133.     if (vim_strchr((char_u *)"/?&", *cmd) == NULL)
  4134.     {
  4135.         EMSG(_(e_backslash));
  4136.         return;
  4137.     }
  4138.     if (*cmd == '&')
  4139.         which_pat = RE_SUBST;    /* use previous substitute pattern */
  4140.     else
  4141.         which_pat = RE_SEARCH;    /* use previous search pattern */
  4142.     ++cmd;
  4143.     pat = (char_u *)"";
  4144.     }
  4145.     else if (*cmd == NUL)
  4146.     {
  4147.     EMSG(_("E148: Regular expression missing from global"));
  4148.     return;
  4149.     }
  4150.     else
  4151.     {
  4152.     delim = *cmd;        /* get the delimiter */
  4153.     if (delim)
  4154.         ++cmd;        /* skip delimiter if there is one */
  4155.     pat = cmd;        /* remember start of pattern */
  4156.     cmd = skip_regexp(cmd, delim, p_magic);
  4157.     if (cmd[0] == delim)            /* end delimiter found */
  4158.         *cmd++ = NUL;            /* replace it with a NUL */
  4159.     }
  4160.  
  4161. #ifdef FEAT_FKMAP    /* when in Farsi mode, reverse the character flow */
  4162.     if (p_altkeymap && curwin->w_p_rl)
  4163.     lrFswap(pat,0);
  4164. #endif
  4165.  
  4166.     if (search_regcomp(pat, RE_BOTH, which_pat, SEARCH_HIS, ®match) == FAIL)
  4167.     {
  4168.     EMSG(_(e_invcmd));
  4169.     return;
  4170.     }
  4171.  
  4172.     /*
  4173.      * pass 1: set marks for each (not) matching line
  4174.      */
  4175.     ndone = 0;
  4176.     for (lnum = eap->line1; lnum <= eap->line2 && !got_int; ++lnum)
  4177.     {
  4178.     /* a match on this line? */
  4179.     match = vim_regexec_multi(®match, curwin, curbuf, lnum, (colnr_T)0);
  4180.     if ((type == 'g' && match) || (type == 'v' && !match))
  4181.     {
  4182.         ml_setmarked(lnum);
  4183.         ndone++;
  4184.     }
  4185.     line_breakcheck();
  4186.     }
  4187.  
  4188.     /*
  4189.      * pass 2: execute the command for each line that has been marked
  4190.      */
  4191.     if (got_int)
  4192.     MSG(_(e_interr));
  4193.     else if (ndone == 0)
  4194.     {
  4195.     if (type == 'v')
  4196.         smsg((char_u *)_("Pattern found in every line: %s"), pat);
  4197.     else
  4198.         smsg((char_u *)_(e_patnotf2), pat);
  4199.     }
  4200.     else
  4201.     global_exe(cmd);
  4202.  
  4203.     ml_clearmarked();       /* clear rest of the marks */
  4204.     vim_free(regmatch.regprog);
  4205. }
  4206.  
  4207. /*
  4208.  * Execute "cmd" on lines marked with ml_setmarked().
  4209.  */
  4210.     void
  4211. global_exe(cmd)
  4212.     char_u    *cmd;
  4213. {
  4214.     linenr_T    old_lcount;    /* b_ml.ml_line_count before the command */
  4215.     linenr_T    lnum;        /* line number according to old situation */
  4216.  
  4217.     /*
  4218.      * Set current position only once for a global command.
  4219.      * If global_busy is set, setpcmark() will not do anything.
  4220.      * If there is an error, global_busy will be incremented.
  4221.      */
  4222.     setpcmark();
  4223.  
  4224.     /* When the command writes a message, don't overwrite the command. */
  4225.     msg_didout = TRUE;
  4226.  
  4227.     global_need_beginline = FALSE;
  4228.     global_busy = 1;
  4229.     old_lcount = curbuf->b_ml.ml_line_count;
  4230.     while (!got_int && (lnum = ml_firstmarked()) != 0 && global_busy == 1)
  4231.     {
  4232.     curwin->w_cursor.lnum = lnum;
  4233.     curwin->w_cursor.col = 0;
  4234.     if (*cmd == NUL || *cmd == '\n')
  4235.         do_cmdline((char_u *)"p", NULL, NULL, DOCMD_NOWAIT);
  4236.     else
  4237.         do_cmdline(cmd, NULL, NULL, DOCMD_NOWAIT);
  4238.     ui_breakcheck();
  4239.     }
  4240.  
  4241.     global_busy = 0;
  4242.     if (global_need_beginline)
  4243.     beginline(BL_WHITE | BL_FIX);
  4244.     else
  4245.     check_cursor();    /* cursor may be beyond the end of the line */
  4246.  
  4247.     /* If it looks like no message was written, allow overwriting the
  4248.      * command with the report for number of changes. */
  4249.     if (msg_col == 0 && msg_scrolled == 0)
  4250.     msg_didout = FALSE;
  4251.  
  4252.     /* If subsitutes done, report number of substitues, otherwise report
  4253.      * number of extra or deleted lines. */
  4254.     if (!do_sub_msg())
  4255.     msgmore(curbuf->b_ml.ml_line_count - old_lcount);
  4256. }
  4257.  
  4258. #ifdef FEAT_VIMINFO
  4259.     int
  4260. read_viminfo_sub_string(virp, force)
  4261.     vir_T    *virp;
  4262.     int        force;
  4263. {
  4264.     if (old_sub != NULL && force)
  4265.     vim_free(old_sub);
  4266.     if (force || old_sub == NULL)
  4267.     old_sub = viminfo_readstring(virp, 1, TRUE);
  4268.     return viminfo_readline(virp);
  4269. }
  4270.  
  4271.     void
  4272. write_viminfo_sub_string(fp)
  4273.     FILE    *fp;
  4274. {
  4275.     if (get_viminfo_parameter('/') != 0 && old_sub != NULL)
  4276.     {
  4277.     fprintf(fp, _("\n# Last Substitute String:\n$"));
  4278.     viminfo_writestring(fp, old_sub);
  4279.     }
  4280. }
  4281. #endif /* FEAT_VIMINFO */
  4282.  
  4283. #if (defined(FEAT_WINDOWS) && defined(FEAT_QUICKFIX)) || defined(PROTO)
  4284. /*
  4285.  * Set up for a tagpreview.
  4286.  */
  4287.     void
  4288. prepare_tagpreview()
  4289. {
  4290.     win_T    *wp;
  4291.  
  4292. #ifdef FEAT_GUI
  4293.     need_mouse_correct = TRUE;
  4294. #endif
  4295.  
  4296.     /*
  4297.      * If there is already a preview window open, use that one.
  4298.      */
  4299.     if (!curwin->w_p_pvw)
  4300.     {
  4301.     for (wp = firstwin; wp != NULL; wp = wp->w_next)
  4302.         if (wp->w_p_pvw)
  4303.         break;
  4304.     if (wp != NULL)
  4305.         win_enter(wp, TRUE);
  4306.     else
  4307.     {
  4308.         /*
  4309.          * There is no preview window open yet.  Create one.
  4310.          */
  4311.         if (win_split(g_do_tagpreview > 0 ? g_do_tagpreview : 0, 0)
  4312.                                       == FAIL)
  4313.         return;
  4314.         curwin->w_p_pvw = TRUE;
  4315.     }
  4316.     }
  4317. }
  4318.  
  4319. #endif
  4320.  
  4321.  
  4322. /*
  4323.  * ":help": open a read-only window on a help file
  4324.  */
  4325.     void
  4326. ex_help(eap)
  4327.     exarg_T    *eap;
  4328. {
  4329.     char_u    *arg;
  4330.     FILE    *helpfd;    /* file descriptor of help file */
  4331.     int        n;
  4332. #ifdef FEAT_WINDOWS
  4333.     win_T    *wp;
  4334. #endif
  4335.     int        num_matches;
  4336.     char_u    **matches;
  4337.     int        need_free = FALSE;
  4338.     char_u    *p;
  4339.  
  4340.     if (eap != NULL)
  4341.     {
  4342.     /*
  4343.      * A ":help" command ends at the first LF, or at a '|' that is
  4344.      * followed by some text.  Set nextcmd to the following command.
  4345.      */
  4346.     for (arg = eap->arg; *arg; ++arg)
  4347.     {
  4348.         if (*arg == '\n' || *arg == '\r' || (*arg == '|' && arg[1] != NUL))
  4349.         {
  4350.         *arg++ = NUL;
  4351.         eap->nextcmd = arg;
  4352.         break;
  4353.         }
  4354.     }
  4355.     arg = eap->arg;
  4356.  
  4357.     if (eap->skip)        /* not executing commands */
  4358.         return;
  4359.     }
  4360.     else
  4361.     arg = (char_u *)"";
  4362.  
  4363.     /*
  4364.      * If an argument is given, check if there is a match for it.
  4365.      */
  4366.     if (*arg != NUL)
  4367.     {
  4368.     /* remove trailing blanks */
  4369.     p = arg + STRLEN(arg) - 1;
  4370.     while (p > arg && vim_iswhite(*p) && p[-1] != '\\')
  4371.         *p-- = NUL;
  4372.  
  4373.     n = find_help_tags(arg, &num_matches, &matches);
  4374.     if (num_matches == 0 || n == FAIL)
  4375.     {
  4376.         EMSG2(_("E149: Sorry, no help for %s"), arg);
  4377.         return;
  4378.     }
  4379.  
  4380.     /* The first match is the best match. */
  4381.     arg = vim_strsave(matches[0]);
  4382.     need_free = TRUE;
  4383.     FreeWild(num_matches, matches);
  4384.     }
  4385.  
  4386. #ifdef FEAT_GUI
  4387.     need_mouse_correct = TRUE;
  4388. #endif
  4389.  
  4390.     /*
  4391.      * Re-use an existing help window or open a new one.
  4392.      */
  4393.     if (!curwin->w_buffer->b_help)
  4394.     {
  4395. #ifdef FEAT_WINDOWS
  4396.     for (wp = firstwin; wp != NULL; wp = wp->w_next)
  4397.         if (wp->w_buffer != NULL && wp->w_buffer->b_help)
  4398.         break;
  4399.     if (wp != NULL && wp->w_buffer->b_nwindows > 0)
  4400.         win_enter(wp, TRUE);
  4401.     else
  4402. #endif
  4403.     {
  4404.         /*
  4405.          * There is no help buffer yet.
  4406.          * Try to open the file specified by the "helpfile" option.
  4407.          */
  4408.         if ((helpfd = mch_fopen((char *)p_hf, READBIN)) == NULL)
  4409.         {
  4410.         smsg((char_u *)_("Sorry, help file \"%s\" not found"), p_hf);
  4411.         goto erret;
  4412.         }
  4413.         fclose(helpfd);
  4414.  
  4415. #ifdef FEAT_WINDOWS
  4416.         /* Split off help window; put it at far top if no position
  4417.          * specified, the current window is vertically split and narrow. */
  4418.         n = WSP_HELP;
  4419. # ifdef FEAT_VERTSPLIT
  4420.         if (cmdmod.split == 0 && curwin->w_width != Columns
  4421.                               && curwin->w_width < 80)
  4422.         n |= WSP_TOP;
  4423. # endif
  4424.         if (win_split(0, n) == FAIL)
  4425. #else
  4426.         /* use current window */
  4427.         if (!can_abandon(curbuf, FALSE))
  4428. #endif
  4429.         goto erret;
  4430.  
  4431. #ifdef FEAT_WINDOWS
  4432.         if (curwin->w_height < p_hh)
  4433.         win_setheight((int)p_hh);
  4434. #endif
  4435.  
  4436.         /*
  4437.          * open help file (do_ecmd() will set b_help flag, readfile() will
  4438.          * set b_p_ro flag)
  4439.          */
  4440.         (void)do_ecmd(0, NULL, NULL, NULL, ECMD_LASTL,
  4441.                            ECMD_HIDE + ECMD_SET_HELP);
  4442.     }
  4443.     }
  4444.  
  4445.     if (!p_im)
  4446.     restart_edit = 0;        /* don't want insert mode in help file */
  4447.  
  4448.     if (arg == NULL || *arg == NUL)
  4449.     {
  4450.     arg = (char_u *)"help.txt";        /* go to the index */
  4451.     need_free = FALSE;
  4452.     }
  4453.     do_tag(arg, DT_HELP, 1, FALSE, TRUE);
  4454.  
  4455.     /*
  4456.      * Always set these options after jumping to a help tag, because the user
  4457.      * may have an autocommand that gets in the way.
  4458.      * accept all chars for keywords, except ' ', '*', '"', '|'.
  4459.      * Only set it when needed, buf_init_chartab() is some work.
  4460.      */
  4461.     p =
  4462. #ifdef EBCDIC
  4463.         (char_u *)"65-255,^*,^|,^\"";
  4464. #else
  4465.         (char_u *)"!-~,^*,^|,^\"";
  4466. #endif
  4467.     if (STRCMP(curbuf->b_p_isk, p) != 0)
  4468.     {
  4469.     set_string_option_direct((char_u *)"isk", -1, p, OPT_FREE|OPT_LOCAL);
  4470.     check_buf_options(curbuf);
  4471.     (void)buf_init_chartab(curbuf, FALSE);
  4472.     }
  4473.  
  4474.     curbuf->b_p_ts = 8;
  4475.     curwin->w_p_list = FALSE;
  4476.  
  4477. erret:
  4478.     if (need_free)
  4479.     vim_free(arg);
  4480. }
  4481.  
  4482.  
  4483. /*
  4484.  * Return a heuristic indicating how well the given string matches.  The
  4485.  * smaller the number, the better the match.  This is the order of priorities,
  4486.  * from best match to worst match:
  4487.  *    - Match with least alpha-numeric characters is better.
  4488.  *    - Match with least total characters is better.
  4489.  *    - Match towards the start is better.
  4490.  *    - Match starting with "+" is worse (feature instead of command)
  4491.  * Assumption is made that the matched_string passed has already been found to
  4492.  * match some string for which help is requested.  webb.
  4493.  */
  4494.     int
  4495. help_heuristic(matched_string, offset, wrong_case)
  4496.     char_u    *matched_string;
  4497.     int        offset;            /* offset for match */
  4498.     int        wrong_case;        /* no matching case */
  4499. {
  4500.     int        num_letters;
  4501.     char_u    *p;
  4502.  
  4503.     num_letters = 0;
  4504.     for (p = matched_string; *p; p++)
  4505.     if (ASCII_ISALNUM(*p))
  4506.         num_letters++;
  4507.  
  4508.     /*
  4509.      * Multiply the number of letters by 100 to give it a much bigger
  4510.      * weighting than the number of characters.
  4511.      * If there only is a match while ignoring case, add 5000.
  4512.      * If the match starts in the middle of a word, add 10000 to put it
  4513.      * somewhere in the last half.
  4514.      * If the match is more than 2 chars from the start, multiply by 200 to
  4515.      * put it after matches at the start.
  4516.      */
  4517.     if (ASCII_ISALNUM(matched_string[offset]) && offset > 0
  4518.                  && ASCII_ISALNUM(matched_string[offset - 1]))
  4519.     offset += 10000;
  4520.     else if (offset > 2)
  4521.     offset *= 200;
  4522.     if (wrong_case)
  4523.     offset += 5000;
  4524.     /* Features are less interesting than the subjects themselves, but "+"
  4525.      * alone is not a feature. */
  4526.     if (matched_string[0] == '+' && matched_string[1] != NUL)
  4527.     offset += 100;
  4528.     return (int)(100 * num_letters + STRLEN(matched_string) + offset);
  4529. }
  4530.  
  4531. /*
  4532.  * Compare functions for qsort() below, that checks the help heuristics number
  4533.  * that has been put after the tagname by find_tags().
  4534.  */
  4535.     static int
  4536. #ifdef __BORLANDC__
  4537. _RTLENTRYF
  4538. #endif
  4539. help_compare(s1, s2)
  4540.     const void    *s1;
  4541.     const void    *s2;
  4542. {
  4543.     char    *p1;
  4544.     char    *p2;
  4545.  
  4546.     p1 = *(char **)s1 + strlen(*(char **)s1) + 1;
  4547.     p2 = *(char **)s2 + strlen(*(char **)s2) + 1;
  4548.     return strcmp(p1, p2);
  4549. }
  4550.  
  4551. /*
  4552.  * Find all help tags matching "arg", sort them and return in matches[], with
  4553.  * the number of matches in num_matches.
  4554.  * The matches will be sorted with a "best" match algorithm.
  4555.  */
  4556.     int
  4557. find_help_tags(arg, num_matches, matches)
  4558.     char_u    *arg;
  4559.     int        *num_matches;
  4560.     char_u    ***matches;
  4561. {
  4562.     char_u    *s, *d;
  4563.     int        i;
  4564.     static char *(mtable[]) = {"*", "g*", "[*", "]*", ":*",
  4565.                    "/*", "/\\*", "\"*", "/\\(\\)",
  4566.                    "?", ":?", "?<CR>", "g?", "g?g?", "g??",
  4567.                    "/\\?",
  4568.                    "[count]", "[quotex]", "[range]",
  4569.                    "[pattern]", "\\|", "\\%$"};
  4570.     static char *(rtable[]) = {"star", "gstar", "[star", "]star", ":star",
  4571.                    "/star", "/\\\\star", "quotestar", "/\\\\(\\\\)",
  4572.                    "?", ":?", "?<CR>", "g?", "g?g?", "g??",
  4573.                    "/\\\\?",
  4574.                    "\\[count]", "\\[quotex]", "\\[range]",
  4575.                    "\\[pattern]", "\\\\bar", "/\\\\%\\$"};
  4576.  
  4577.     d = IObuff;            /* assume IObuff is long enough! */
  4578.  
  4579.     /*
  4580.      * Recognize a few exceptions to the rule.    Some strings that contain '*'
  4581.      * with "star".  Otherwise '*' is recognized as a wildcard.
  4582.      */
  4583.     for (i = sizeof(mtable) / sizeof(char *); --i >= 0; )
  4584.     if (STRCMP(arg, mtable[i]) == 0)
  4585.     {
  4586.         STRCPY(d, rtable[i]);
  4587.         break;
  4588.     }
  4589.  
  4590.     if (i < 0)    /* no match in table */
  4591.     {
  4592.     /* Replace "\S" with "/\\S", etc.  Otherwise every tag is matched.
  4593.      * Also replace "\%^" and "\%(", they match every tag too.
  4594.      * And also "\_$" and "\_^". */
  4595.  
  4596.     if (arg[0] == '\\'
  4597.         && ((arg[1] != NUL && arg[2] == NUL)
  4598.             || ((arg[1] == '%' || arg[1] == '_')
  4599.                       && arg[2] != NUL && arg[3] == NUL)))
  4600.     {
  4601.         STRCPY(d, "/\\\\");
  4602.         STRCPY(d + 3, arg + 1);
  4603.         /* Check for "/\\_$", should be "/\\_\$" */
  4604.         if (d[3] == '_' && d[4] == '$')
  4605.         STRCPY(d + 4, "\\$");
  4606.     }
  4607.     else
  4608.     {
  4609.       /* replace "[:...:]" with "\[:...:]"; "[+...]" with "\[++...]" */
  4610.         if (arg[0] == '[' && (arg[1] == ':'
  4611.                      || (arg[1] == '+' && arg[2] == '+')))
  4612.           *d++ = '\\';
  4613.  
  4614.       for (s = arg; *s; ++s)
  4615.       {
  4616.         /*
  4617.          * Replace "|" with "bar" and '"' with "quote" to match the name of
  4618.          * the tags for these commands.
  4619.          * Replace "*" with ".*" and "?" with "." to match command line
  4620.          * completion.
  4621.          * Insert a backslash before '~', '$' and '.' to avoid their
  4622.          * special meaning.
  4623.          */
  4624.         if (d - IObuff > IOSIZE - 10)    /* getting too long!? */
  4625.         break;
  4626.         switch (*s)
  4627.         {
  4628.         case '|':   STRCPY(d, "bar");
  4629.                 d += 3;
  4630.                 continue;
  4631.         case '"':   STRCPY(d, "quote");
  4632.                 d += 5;
  4633.                 continue;
  4634.         case '*':   *d++ = '.';
  4635.                 break;
  4636.         case '?':   *d++ = '.';
  4637.                 continue;
  4638.         case '$':
  4639.         case '.':
  4640.         case '~':   *d++ = '\\';
  4641.                 break;
  4642.         }
  4643.  
  4644.         /*
  4645.          * Replace "^x" by "CTRL-X". Don't do this for "^_" to make
  4646.          * ":help i_^_CTRL-D" work.
  4647.          * Insert '-' before and after "CTRL-X" when applicable.
  4648.          */
  4649.         if (*s < ' ' || (*s == '^' && s[1] && (ASCII_ISALPHA(s[1])
  4650.                || vim_strchr((char_u *)"?@[\\]^", s[1]) != NULL)))
  4651.         {
  4652.         if (d > IObuff && d[-1] != '_')
  4653.             *d++ = '_';        /* prepend a '_' */
  4654.         STRCPY(d, "CTRL-");
  4655.         d += 5;
  4656.         if (*s < ' ')
  4657. #ifdef EBCDIC
  4658.             *d++ = CtrlChar(*s);
  4659. #else
  4660.             *d++ = *s + '@';
  4661. #endif
  4662.         else
  4663.             *d++ = *++s;
  4664.         if (s[1] != NUL && s[1] != '_')
  4665.             *d++ = '_';        /* append a '_' */
  4666.         continue;
  4667.         }
  4668.         else if (*s == '^')        /* "^" or "CTRL-^" or "^_" */
  4669.         *d++ = '\\';
  4670.  
  4671.         /*
  4672.          * Insert a backslash before a backslash after a slash, for search
  4673.          * pattern tags: "/\|" --> "/\\|".
  4674.          */
  4675.         else if (s[0] == '\\' && s[1] != '\\'
  4676.                            && *arg == '/' && s == arg + 1)
  4677.         *d++ = '\\';
  4678.  
  4679.         *d++ = *s;
  4680.  
  4681.         /*
  4682.          * If tag starts with ', toss everything after a second '. Fixes
  4683.          * CTRL-] on 'option'. (would include the trailing '.').
  4684.          */
  4685.         if (*s == '\'' && s > arg && *arg == '\'')
  4686.         break;
  4687.       }
  4688.       *d = NUL;
  4689.     }
  4690.     }
  4691.  
  4692.     *matches = (char_u **)"";
  4693.     *num_matches = 0;
  4694.     if (find_tags(IObuff, num_matches, matches,
  4695.     TAG_HELP | TAG_REGEXP | TAG_NAMES | TAG_VERBOSE, (int)MAXCOL) == OK)
  4696.     /*
  4697.      * Sort the matches found on the heuristic number that is after the
  4698.      * tag name.
  4699.      */
  4700.     qsort((void *)*matches, (size_t)*num_matches,
  4701.                           sizeof(char_u *), help_compare)
  4702.     ;
  4703.     return OK;
  4704. }
  4705.  
  4706. /*
  4707.  * After reading a help file: May cleanup a help buffer when syntax
  4708.  * highlighting is not used.
  4709.  */
  4710.     void
  4711. fix_help_buffer()
  4712. {
  4713.     linenr_T    lnum;
  4714.     char_u    *line;
  4715.     int        in_example = FALSE;
  4716.     int        len;
  4717.     char_u    *p;
  4718.     char_u    *rt;
  4719.     int        mustfree;
  4720.  
  4721.     /* set filetype to "help". */
  4722.     set_option_value((char_u *)"ft", 0L, (char_u *)"help", OPT_LOCAL);
  4723.  
  4724. #ifdef FEAT_SYN_HL
  4725.     if (!syntax_present(curbuf))
  4726. #endif
  4727.     {
  4728.     for (lnum = 1; lnum <= curbuf->b_ml.ml_line_count; ++lnum)
  4729.     {
  4730.         line = ml_get_buf(curbuf, lnum, FALSE);
  4731.         len = (int)STRLEN(line);
  4732.         if (in_example && len > 0 && !vim_iswhite(line[0]))
  4733.         {
  4734.         /* End of example: non-white or '<' in first column. */
  4735.         if (line[0] == '<')
  4736.         {
  4737.             /* blank-out a '<' in the first column */
  4738.             line = ml_get_buf(curbuf, lnum, TRUE);
  4739.             line[0] = ' ';
  4740.         }
  4741.         in_example = FALSE;
  4742.         }
  4743.         if (!in_example && len > 0)
  4744.         {
  4745.         if (line[len - 1] == '>' && (len == 1 || line[len - 2] == ' '))
  4746.         {
  4747.             /* blank-out a '>' in the last column (start of example) */
  4748.             line = ml_get_buf(curbuf, lnum, TRUE);
  4749.             line[len - 1] = ' ';
  4750.             in_example = TRUE;
  4751.         }
  4752.         else if (line[len - 1] == '~')
  4753.         {
  4754.             /* blank-out a '~' at the end of line (header marker) */
  4755.             line = ml_get_buf(curbuf, lnum, TRUE);
  4756.             line[len - 1] = ' ';
  4757.         }
  4758.         }
  4759.     }
  4760.     }
  4761.  
  4762.     /*
  4763.      * In the "help.txt" file, add the locally added help files.
  4764.      * This uses the very first line in the help file.
  4765.      */
  4766.     if (fnamecmp(gettail(curbuf->b_fname), "help.txt") == 0)
  4767.     {
  4768.     for (lnum = 1; lnum < curbuf->b_ml.ml_line_count; ++lnum)
  4769.     {
  4770.         line = ml_get_buf(curbuf, lnum, FALSE);
  4771.         if (STRNCMP(line, "LOCAL ADDITIONS", 15) == 0)
  4772.         {
  4773.         /* Go through all directories in 'runtimepath', skipping
  4774.          * $VIMRUNTIME. */
  4775.         p = p_rtp;
  4776.         while (*p != NUL)
  4777.         {
  4778.             copy_option_part(&p, NameBuff, MAXPATHL, ",");
  4779.             mustfree = FALSE;
  4780.             rt = vim_getenv((char_u *)"VIMRUNTIME", &mustfree);
  4781.             if (fnamecmp(NameBuff, rt) != 0)
  4782.             {
  4783.             int    fcount;
  4784.             char_u    **fnames;
  4785.             FILE    *fd;
  4786.             char_u    *s;
  4787.             int    fi;
  4788.  
  4789.             /* Find all "doc/ *.txt" files in this directory. */
  4790.             add_pathsep(NameBuff);
  4791.             STRCAT(NameBuff, "doc/*.txt");
  4792.             if (gen_expand_wildcards(1, &NameBuff, &fcount,
  4793.                          &fnames, EW_FILE|EW_SILENT) == OK
  4794.                 && fcount > 0)
  4795.             {
  4796.                 for (fi = 0; fi < fcount; ++fi)
  4797.                 {
  4798.                 fd = fopen((char *)fnames[fi], "r");
  4799.                 if (fd != NULL)
  4800.                 {
  4801.                     vim_fgets(IObuff, IOSIZE, fd);
  4802.                     if (IObuff[0] == '*'
  4803.                         && (s = vim_strchr(IObuff + 1, '*'))
  4804.                                       != NULL)
  4805.                     {
  4806.                     /* Change tag definition to a
  4807.                      * reference and remove <CR>/<NL>. */
  4808.                     IObuff[0] = '|';
  4809.                     *s = '|';
  4810.                     while (*s != NUL)
  4811.                     {
  4812.                         if (*s == '\r' || *s == '\n')
  4813.                         *s = NUL;
  4814.                         ++s;
  4815.                     }
  4816.                     ml_append(lnum, IObuff, (colnr_T)0,
  4817.                                        FALSE);
  4818.                     ++lnum;
  4819.                     }
  4820.                     fclose(fd);
  4821.                 }
  4822.                 }
  4823.                 FreeWild(fcount, fnames);
  4824.             }
  4825.             }
  4826.             if (mustfree)
  4827.             vim_free(rt);
  4828.         }
  4829.         break;
  4830.         }
  4831.     }
  4832.     }
  4833. }
  4834.  
  4835. #if defined(FEAT_EX_EXTRA) || defined(PROTO)
  4836. /*
  4837.  * ":helptags"
  4838.  */
  4839.     void
  4840. ex_helptags(eap)
  4841.     exarg_T    *eap;
  4842. {
  4843.     FILE    *fd_tags;
  4844.     FILE    *fd;
  4845.     garray_T    ga;
  4846.     int        filecount;
  4847.     char_u    **files;
  4848.     char_u    *p1, *p2;
  4849.     int        fi;
  4850.     char_u    *s;
  4851.     int        i;
  4852.     char_u    *fname;
  4853.  
  4854.     if (!mch_isdir(eap->arg))
  4855.     {
  4856.     EMSG2(_("E150: Not a directory: %s"), eap->arg);
  4857.     return;
  4858.     }
  4859.  
  4860.     /*
  4861.      * Find all *.txt files.
  4862.      */
  4863.     STRCPY(NameBuff, eap->arg);
  4864.     add_pathsep(NameBuff);
  4865.     STRCAT(NameBuff, "*.txt");
  4866.     if (gen_expand_wildcards(1, &NameBuff, &filecount, &files,
  4867.                             EW_FILE|EW_SILENT) == FAIL
  4868.         || filecount == 0)
  4869.     {
  4870.     EMSG2("E151: No match: %s", NameBuff);
  4871.     return;
  4872.     }
  4873.  
  4874.     /*
  4875.      * Open the tags file for writing.
  4876.      * Do this before scanning through all the files.
  4877.      */
  4878.     STRCPY(NameBuff, eap->arg);
  4879.     add_pathsep(NameBuff);
  4880.     STRCAT(NameBuff, "tags");
  4881.     fd_tags = fopen((char *)NameBuff, "w");
  4882.     if (fd_tags == NULL)
  4883.     {
  4884.     EMSG2(_("E152: Cannot open %s for writing"), NameBuff);
  4885.     FreeWild(filecount, files);
  4886.     return;
  4887.     }
  4888.  
  4889.     /*
  4890.      * Go over all the files and extract the tags.
  4891.      */
  4892.     ga_init2(&ga, (int)sizeof(char_u *), 100);
  4893.     for (fi = 0; fi < filecount && !got_int; ++fi)
  4894.     {
  4895.     fd = fopen((char *)files[fi], "r");
  4896.     if (fd == NULL)
  4897.     {
  4898.         EMSG2(_("E153: Unable to open %s for reading"), files[fi]);
  4899.         continue;
  4900.     }
  4901.     fname = gettail(files[fi]);
  4902.  
  4903.     while (!vim_fgets(IObuff, IOSIZE, fd) && !got_int)
  4904.     {
  4905.         p1 = vim_strchr(IObuff, '*');    /* find first '*' */
  4906.         while (p1 != NULL)
  4907.         {
  4908.         p2 = vim_strchr(p1 + 1, '*');    /* find second '*' */
  4909.         if (p2 != NULL && p2 > p1 + 1)    /* skip "*" and "**" */
  4910.         {
  4911.             for (s = p1 + 1; s < p2; ++s)
  4912.             if (*s == ' ' || *s == '\t' || *s == '|')
  4913.                 break;
  4914.  
  4915.             /*
  4916.              * Only accept a *tag* when it consists of valid
  4917.              * characters, there is no '-' before it and is followed
  4918.              * by a white character or end-of-line.
  4919.              */
  4920.             if (s == p2
  4921.                 && (p1 == IObuff || p1[-1] != '-')
  4922.                 && (vim_strchr((char_u *)" \t\n\r", s[1]) != NULL
  4923.                 || s[1] == '\0'))
  4924.             {
  4925.             *p2 = '\0';
  4926.             ++p1;
  4927.             if (ga_grow(&ga, 1) == FAIL)
  4928.             {
  4929.                 got_int = TRUE;
  4930.                 break;
  4931.             }
  4932.             s = alloc((unsigned)(p2 - p1 + STRLEN(fname) + 2));
  4933.             if (s == NULL)
  4934.             {
  4935.                 got_int = TRUE;
  4936.                 break;
  4937.             }
  4938.             ((char_u **)ga.ga_data)[ga.ga_len] = s;
  4939.             ++ga.ga_len;
  4940.             --ga.ga_room;
  4941.             sprintf((char *)s, "%s\t%s", p1, fname);
  4942.  
  4943.             /* find next '*' */
  4944.             p2 = vim_strchr(p2 + 1, '*');
  4945.             }
  4946.         }
  4947.         p1 = p2;
  4948.         }
  4949.         line_breakcheck();
  4950.     }
  4951.  
  4952.     fclose(fd);
  4953.     }
  4954.  
  4955.     FreeWild(filecount, files);
  4956.  
  4957.     if (!got_int)
  4958.     {
  4959.     /*
  4960.      * Sort the tags.
  4961.      */
  4962.     sort_strings((char_u **)ga.ga_data, ga.ga_len);
  4963.  
  4964.     /*
  4965.      * Check for duplicates.
  4966.      */
  4967.     for (i = 1; i < ga.ga_len; ++i)
  4968.     {
  4969.         p1 = ((char_u **)ga.ga_data)[i - 1];
  4970.         p2 = ((char_u **)ga.ga_data)[i];
  4971.         while (*p1 == *p2)
  4972.         {
  4973.         if (*p2 == '\t')
  4974.         {
  4975.             *p2 = NUL;
  4976.             sprintf((char *)NameBuff,
  4977.                 _("E154: Duplicate tag \"%s\" in file %s"),
  4978.                 ((char_u **)ga.ga_data)[i], p2 + 1);
  4979.             EMSG(NameBuff);
  4980.             *p2 = '\t';
  4981.             break;
  4982.         }
  4983.         ++p1;
  4984.         ++p2;
  4985.         }
  4986.     }
  4987.  
  4988.     /*
  4989.      * Write the tags into the file.
  4990.      */
  4991.     for (i = 0; i < ga.ga_len; ++i)
  4992.     {
  4993.         s = ((char_u **)ga.ga_data)[i];
  4994.         fprintf(fd_tags, "%s\t/*", s);
  4995.         for (p1 = s; *p1 != '\t'; ++p1)
  4996.         {
  4997.         /* insert backslash before '\\' and '/' */
  4998.         if (*p1 == '\\' || *p1 == '/')
  4999.             putc('\\', fd_tags);
  5000.         putc(*p1, fd_tags);
  5001.         }
  5002.         fprintf(fd_tags, "*\n");
  5003.     }
  5004.     }
  5005.  
  5006.     for (i = 0; i < ga.ga_len; ++i)
  5007.     vim_free(((char_u **)ga.ga_data)[i]);
  5008.     ga_clear(&ga);
  5009.     fclose(fd_tags);        /* there is no check for an error... */
  5010. }
  5011. #endif
  5012.  
  5013. #if defined(FEAT_SIGNS) || defined(PROTO)
  5014.  
  5015. /*
  5016.  * Struct to hold the sign properties.
  5017.  */
  5018. typedef struct sign sign_T;
  5019.  
  5020. struct sign
  5021. {
  5022.     sign_T    *sn_next;    /* next sign in list */
  5023.     int        sn_typenr;    /* type number of sign (negative if not equal
  5024.                    to name) */
  5025.     char_u    *sn_name;    /* name of sign */
  5026.     char_u    *sn_icon;    /* name of pixmap */
  5027. #ifdef FEAT_SIGN_ICONS
  5028.     XImage    *sn_image;    /* icon image */
  5029. #endif
  5030.     char_u    *sn_text;    /* text used instead of pixmap */
  5031.     int        sn_line_hl;    /* highlight ID for line */
  5032.     int        sn_text_hl;    /* highlight ID for text */
  5033. };
  5034.  
  5035. #define MAX_TYPENR 255        /* depends on sattr_T */
  5036. static sign_T    *first_sign = NULL;
  5037. static int    last_sign_typenr = MAX_TYPENR;    /* is decremented */
  5038.  
  5039. static void sign_list_defined __ARGS((sign_T *sp));
  5040.  
  5041. /*
  5042.  * ":sign" command
  5043.  */
  5044.     void
  5045. ex_sign(eap)
  5046.     exarg_T    *eap;
  5047. {
  5048.     char_u    *arg = eap->arg;
  5049.     char_u    *p;
  5050.     int        idx;
  5051.     sign_T    *sp;
  5052.     sign_T    *sp_prev;
  5053.     buf_T    *buf;
  5054.     static char    *cmds[] = {
  5055.             "define",
  5056. #define SIGNCMD_DEFINE    0
  5057.             "undefine",
  5058. #define SIGNCMD_UNDEFINE 1
  5059.             "list",
  5060. #define SIGNCMD_LIST    2
  5061.             "place",
  5062. #define SIGNCMD_PLACE    3
  5063.             "unplace",
  5064. #define SIGNCMD_UNPLACE    4
  5065.             "jump",
  5066. #define SIGNCMD_JUMP    5
  5067. #define SIGNCMD_LAST    6
  5068.     };
  5069.  
  5070.     /* Parse the subcommand. */
  5071.     p = skiptowhite(arg);
  5072.     if (*p != NUL)
  5073.     *p++ = NUL;
  5074.     for (idx = 0; ; ++idx)
  5075.     {
  5076.     if (idx == SIGNCMD_LAST)
  5077.     {
  5078.         EMSG2(_("E160: Unknown sign command: %s"), arg);
  5079.         return;
  5080.     }
  5081.     if (STRCMP(arg, cmds[idx]) == 0)
  5082.         break;
  5083.     }
  5084.     arg = skipwhite(p);
  5085.  
  5086.     if (idx <= SIGNCMD_LIST)
  5087.     {
  5088.     /*
  5089.      * Define, undefine or list signs.
  5090.      */
  5091.     if (idx == SIGNCMD_LIST && *arg == NUL)
  5092.     {
  5093.         /* ":sign list": list all defined signs */
  5094.         for (sp = first_sign; sp != NULL; sp = sp->sn_next)
  5095.         sign_list_defined(sp);
  5096.     }
  5097.     else if (*arg == NUL)
  5098.         EMSG(_("E156: Missing sign name"));
  5099.     else
  5100.     {
  5101.         p = skiptowhite(arg);
  5102.         if (*p != NUL)
  5103.         *p++ = NUL;
  5104.         sp_prev = NULL;
  5105.         for (sp = first_sign; sp != NULL; sp = sp->sn_next)
  5106.         {
  5107.         if (STRCMP(sp->sn_name, arg) == 0)
  5108.             break;
  5109.         sp_prev = sp;
  5110.         }
  5111.         if (idx == SIGNCMD_DEFINE)
  5112.         {
  5113.         /* ":sign define {name} ...": define a sign */
  5114.         if (sp == NULL)
  5115.         {
  5116.             /* Allocate a new sign. */
  5117.             sp = (sign_T *)alloc_clear((unsigned)sizeof(sign_T));
  5118.             if (sp == NULL)
  5119.             return;
  5120.             if (sp_prev == NULL)
  5121.             first_sign = sp;
  5122.             else
  5123.             sp_prev->sn_next = sp;
  5124.             sp->sn_name = vim_strnsave(arg, (int)(p - arg));
  5125.  
  5126.             /* If the name is a number use that for the typenr,
  5127.              * otherwise use a negative number. */
  5128.             if (isdigit(*arg))
  5129.             sp->sn_typenr = atoi((char *)arg);
  5130.             else
  5131.             {
  5132.             sign_T    *lp;
  5133.             int    start = last_sign_typenr;
  5134.  
  5135.             for (lp = first_sign; lp != NULL; lp = lp->sn_next)
  5136.             {
  5137.                 if (lp->sn_typenr == last_sign_typenr)
  5138.                 {
  5139.                 --last_sign_typenr;
  5140.                 if (last_sign_typenr == 0)
  5141.                     last_sign_typenr = MAX_TYPENR;
  5142.                 if (last_sign_typenr == start)
  5143.                 {
  5144.                     EMSG(_("E255: Too many signs defined"));
  5145.                     return;
  5146.                 }
  5147.                 lp = first_sign;
  5148.                 continue;
  5149.                 }
  5150.             }
  5151.  
  5152.             sp->sn_typenr = last_sign_typenr--;
  5153.             if (last_sign_typenr == 0)
  5154.                 last_sign_typenr = MAX_TYPENR; /* wrap around */
  5155.             }
  5156.         }
  5157.  
  5158.         /* set values for a defined sign. */
  5159.         for (;;)
  5160.         {
  5161.             arg = skipwhite(p);
  5162.             if (*arg == NUL)
  5163.             break;
  5164.             p = skiptowhite(arg);
  5165.             if (STRNCMP(arg, "icon=", 5) == 0)
  5166.             {
  5167.             arg += 5;
  5168.             vim_free(sp->sn_icon);
  5169.             sp->sn_icon = vim_strnsave(arg, (int)(p - arg));
  5170. #ifdef FEAT_SIGN_ICONS
  5171.             if (gui.in_use)
  5172.             {
  5173.                 if (sp->sn_image != NULL)
  5174.                 gui_mch_destroy_sign(sp->sn_image);
  5175.                 sp->sn_image = gui_mch_register_sign(sp->sn_icon);
  5176.             }
  5177. #endif
  5178.             }
  5179.             else if (STRNCMP(arg, "text=", 5) == 0)
  5180.             {
  5181.             arg += 5;
  5182.             /* Currently must have two printable characters. */
  5183.             if (!vim_isprintc(arg[0]) || !vim_isprintc(arg[1])
  5184.                                  || p - arg != 2)
  5185.             {
  5186.                 EMSG2(_("E239: Invalid sign text: %s"), arg);
  5187.                 return;
  5188.             }
  5189.             vim_free(sp->sn_text);
  5190.             sp->sn_text = vim_strnsave(arg, (int)(p - arg));
  5191.             }
  5192.             else if (STRNCMP(arg, "linehl=", 7) == 0)
  5193.             {
  5194.             arg += 7;
  5195.             sp->sn_line_hl = syn_check_group(arg, (int)(p - arg));
  5196.             }
  5197.             else if (STRNCMP(arg, "texthl=", 7) == 0)
  5198.             {
  5199.             arg += 7;
  5200.             sp->sn_text_hl = syn_check_group(arg, (int)(p - arg));
  5201.             }
  5202.             else
  5203.             {
  5204.             EMSG2(_(e_invarg2), arg);
  5205.             return;
  5206.             }
  5207.         }
  5208.         }
  5209.         else if (sp == NULL)
  5210.         EMSG2(_("E155: Unknown sign: %s"), arg);
  5211.         else if (idx == SIGNCMD_LIST)
  5212.         /* ":sign list {name}" */
  5213.         sign_list_defined(sp);
  5214.         else
  5215.         {
  5216.         /* ":sign undefine {name}" */
  5217.         vim_free(sp->sn_name);
  5218.         vim_free(sp->sn_icon);
  5219. #ifdef FEAT_SIGN_ICONS
  5220.         if (sp->sn_image != NULL)
  5221.             gui_mch_destroy_sign(sp->sn_image);
  5222. #endif
  5223.         vim_free(sp->sn_text);
  5224.         if (sp_prev == NULL)
  5225.             first_sign = sp->sn_next;
  5226.         else
  5227.             sp_prev->sn_next = sp->sn_next;
  5228.         vim_free(sp);
  5229.         }
  5230.     }
  5231.     }
  5232.     else
  5233.     {
  5234.     int        id = -1;
  5235.     linenr_T    lnum = -1;
  5236.     char_u        *sign_name = NULL;
  5237.     char_u        *arg1;
  5238.  
  5239.     if (*arg == NUL)
  5240.     {
  5241.         if (idx == SIGNCMD_PLACE)
  5242.         {
  5243.         /* ":sign place": list placed signs in all buffers */
  5244.         sign_list_placed(NULL);
  5245.         }
  5246.         else if (idx == SIGNCMD_UNPLACE)
  5247.         {
  5248.         /* ":sign unplace": remove placed sign at cursor */
  5249.         id = buf_findsign_id(curwin->w_buffer, curwin->w_cursor.lnum);
  5250.         if (id > 0)
  5251.         {
  5252.             buf_delsign(curwin->w_buffer, id);
  5253.             update_debug_sign(curwin->w_buffer, curwin->w_cursor.lnum);
  5254.         }
  5255.         else
  5256.             EMSG(_("E159: Missing sign number"));
  5257.         }
  5258.         else
  5259.         EMSG(_(e_argreq));
  5260.         return;
  5261.     }
  5262.  
  5263.     if (idx == SIGNCMD_UNPLACE && arg[0] == '*' && arg[1] == NUL)
  5264.     {
  5265.         /* ":sign unplace *": remove all placed signs */
  5266.         buf_delete_all_signs();
  5267.         return;
  5268.     }
  5269.  
  5270.     /* first arg could be placed sign id */
  5271.     arg1 = arg;
  5272.     if (isdigit(*arg))
  5273.     {
  5274.         id = getdigits(&arg);
  5275.         if (!vim_iswhite(*arg) && *arg != NUL)
  5276.         {
  5277.         id = -1;
  5278.         arg = arg1;
  5279.         }
  5280.         else
  5281.         {
  5282.         arg = skipwhite(arg);
  5283.         if (idx == SIGNCMD_UNPLACE && *arg == NUL)
  5284.         {
  5285.             /* ":sign unplace {id}": remove placed sign by number */
  5286.             for (buf = firstbuf; buf != NULL; buf = buf->b_next)
  5287.             if ((lnum = buf_delsign(buf, id)) != 0)
  5288.                 update_debug_sign(buf, lnum);
  5289.             return;
  5290.         }
  5291.         }
  5292.     }
  5293.  
  5294.     /*
  5295.      * Check for line={lnum} name={name} and file={fname} or buffer={nr}.
  5296.      * Leave "arg" pointing to {fname}.
  5297.      */
  5298.     for (;;)
  5299.     {
  5300.         if (STRNCMP(arg, "line=", 5) == 0)
  5301.         {
  5302.         arg += 5;
  5303.         lnum = atoi((char *)arg);
  5304.         arg = skiptowhite(arg);
  5305.         }
  5306.         else if (STRNCMP(arg, "name=", 5) == 0)
  5307.         {
  5308.         arg += 5;
  5309.         sign_name = arg;
  5310.         arg = skiptowhite(arg);
  5311.         if (*arg != NUL)
  5312.             *arg++ = NUL;
  5313.         }
  5314.         else if (STRNCMP(arg, "file=", 5) == 0)
  5315.         {
  5316.         arg += 5;
  5317.         buf = buflist_findname(arg);
  5318.         break;
  5319.         }
  5320.         else if (STRNCMP(arg, "buffer=", 7) == 0)
  5321.         {
  5322.         arg += 7;
  5323.         buf = buflist_findnr(atoi((char *)arg));
  5324.         break;
  5325.         }
  5326.         else
  5327.         {
  5328.         EMSG(_(e_invarg));
  5329.         return;
  5330.         }
  5331.         arg = skipwhite(arg);
  5332.     }
  5333.  
  5334.     if (buf == NULL)
  5335.     {
  5336.         EMSG2(_("E158: Invalid buffer name: %s"), arg);
  5337.     }
  5338.     else if (id <= 0)
  5339.     {
  5340.         if (lnum >= 0 || sign_name != NULL)
  5341.         EMSG(_(e_invarg));
  5342.         else
  5343.         /* ":sign place file={fname}": list placed signs in one file */
  5344.         sign_list_placed(buf);
  5345.     }
  5346.     else if (idx == SIGNCMD_JUMP)
  5347.     {
  5348.         /* ":sign jump {id} file={fname}" */
  5349.         if (lnum >= 0 || sign_name != NULL)
  5350.         EMSG(_(e_invarg));
  5351.         else if ((lnum = buf_findsign(buf, id)) > 0)
  5352.         {                /* goto a sign ... */
  5353.         if (buf_jump_open_win(buf) != NULL)
  5354.         {            /* ... in a current window */
  5355.             curwin->w_cursor.lnum = lnum;
  5356.             check_cursor_lnum();
  5357.             beginline(BL_WHITE);
  5358.         }
  5359.         else
  5360.         {            /* ... not currently in a window */
  5361.             char_u    *cmd;
  5362.  
  5363.             cmd = alloc((unsigned)STRLEN(buf->b_fname) + 25);
  5364.             if (cmd == NULL)
  5365.             return;
  5366.             sprintf((char *)cmd, "e +%ld %s", (long)lnum, buf->b_fname);
  5367.             do_cmdline_cmd(cmd);
  5368.             vim_free(cmd);
  5369.         }
  5370. #ifdef FEAT_FOLDING
  5371.         foldOpenCursor();
  5372. #endif
  5373.         }
  5374.         else
  5375.         EMSGN(_("E157: Invalid sign ID: %ld"), id);
  5376.     }
  5377.     else if (idx == SIGNCMD_UNPLACE)
  5378.     {
  5379.         /* ":sign unplace {id} file={fname}" */
  5380.         if (lnum >= 0 || sign_name != NULL)
  5381.         EMSG(_(e_invarg));
  5382.         else
  5383.         {
  5384.         lnum = buf_delsign(buf, id);
  5385.         update_debug_sign(buf, lnum);
  5386.         }
  5387.     }
  5388.         /* idx == SIGNCMD_PLACE */
  5389.     else if (sign_name != NULL)
  5390.     {
  5391.         for (sp = first_sign; sp != NULL; sp = sp->sn_next)
  5392.         if (STRCMP(sp->sn_name, sign_name) == 0)
  5393.             break;
  5394.         if (sp == NULL)
  5395.         {
  5396.         EMSG2(_("E155: Unknown sign: %s"), sign_name);
  5397.         return;
  5398.         }
  5399.         if (lnum > 0)
  5400.         /* ":sign place {id} line={lnum} name={name} file={fname}":
  5401.          * place a sign */
  5402.         buf_addsign(buf, id, lnum, sp->sn_typenr);
  5403.         else
  5404.         /* ":sign place {id} file={fname}": change sign type */
  5405.         lnum = buf_change_sign_type(buf, id, sp->sn_typenr);
  5406.         update_debug_sign(buf, lnum);
  5407.     }
  5408.     else
  5409.         EMSG(_(e_invarg));
  5410.     }
  5411. }
  5412.  
  5413. #if defined(FEAT_SIGN_ICONS) || defined(PROTO)
  5414. /*
  5415.  * Allocate the icons.  Called when the GUI has started.  Allows defining
  5416.  * signs before it starts.
  5417.  */
  5418.     void
  5419. sign_gui_started()
  5420. {
  5421.     sign_T    *sp;
  5422.  
  5423.     for (sp = first_sign; sp != NULL; sp = sp->sn_next)
  5424.     if (sp->sn_icon != NULL)
  5425.         sp->sn_image = gui_mch_register_sign(sp->sn_icon);
  5426. }
  5427. #endif
  5428.  
  5429. /*
  5430.  * List one sign.
  5431.  */
  5432.     static void
  5433. sign_list_defined(sp)
  5434.     sign_T    *sp;
  5435. {
  5436.     char_u    *p;
  5437.  
  5438.     smsg((char_u *)"sign %s", sp->sn_name);
  5439.     if (sp->sn_icon != NULL)
  5440.     {
  5441.     MSG_PUTS(" icon=");
  5442.     msg_outtrans(sp->sn_icon);
  5443. #ifdef FEAT_SIGN_ICONS
  5444.     if (sp->sn_image == NULL)
  5445.         MSG_PUTS(" (NOT FOUND)");
  5446. #else
  5447.     MSG_PUTS(" (not supported)");
  5448. #endif
  5449.     }
  5450.     if (sp->sn_text != NULL)
  5451.     {
  5452.     MSG_PUTS(" text=");
  5453.     msg_outtrans(sp->sn_text);
  5454.     }
  5455.     if (sp->sn_line_hl > 0)
  5456.     {
  5457.     MSG_PUTS(" linehl=");
  5458.     p = get_highlight_name(NULL, sp->sn_line_hl - 1);
  5459.     if (p == NULL)
  5460.         MSG_PUTS("NONE");
  5461.     else
  5462.         msg_puts(p);
  5463.     }
  5464.     if (sp->sn_text_hl > 0)
  5465.     {
  5466.     MSG_PUTS(" texthl=");
  5467.     p = get_highlight_name(NULL, sp->sn_text_hl - 1);
  5468.     if (p == NULL)
  5469.         MSG_PUTS("NONE");
  5470.     else
  5471.         msg_puts(p);
  5472.     }
  5473. }
  5474.  
  5475. /*
  5476.  * Get highlighting attribute for sign "typenr".
  5477.  * If "line" is TRUE: line highl, if FALSE: text highl.
  5478.  */
  5479.     int
  5480. sign_get_attr(typenr, line)
  5481.     int        typenr;
  5482.     int        line;
  5483. {
  5484.     sign_T    *sp;
  5485.  
  5486.     for (sp = first_sign; sp != NULL; sp = sp->sn_next)
  5487.     if (sp->sn_typenr == typenr)
  5488.     {
  5489.         if (line)
  5490.         {
  5491.         if (sp->sn_line_hl > 0)
  5492.             return syn_id2attr(sp->sn_line_hl);
  5493.         }
  5494.         else
  5495.         {
  5496.         if (sp->sn_text_hl > 0)
  5497.             return syn_id2attr(sp->sn_text_hl);
  5498.         }
  5499.         break;
  5500.     }
  5501.     return 0;
  5502. }
  5503.  
  5504. /*
  5505.  * Get text mark for sign "typenr".
  5506.  * Returns NULL if there isn't one.
  5507.  */
  5508.     char_u *
  5509. sign_get_text(typenr)
  5510.     int        typenr;
  5511. {
  5512.     sign_T    *sp;
  5513.  
  5514.     for (sp = first_sign; sp != NULL; sp = sp->sn_next)
  5515.     if (sp->sn_typenr == typenr)
  5516.         return sp->sn_text;
  5517.     return NULL;
  5518. }
  5519.  
  5520. #if defined(FEAT_SIGN_ICONS) || defined(PROTO)
  5521.     void *
  5522. sign_get_image(typenr)
  5523.     int        typenr;        /* the attribute which may have a sign */
  5524. {
  5525.     sign_T    *sp;
  5526.  
  5527.     for (sp = first_sign; sp != NULL; sp = sp->sn_next)
  5528.     if (sp->sn_typenr == typenr)
  5529.         return (void *)sp->sn_image;
  5530.     return NULL;
  5531. }
  5532. #endif
  5533.  
  5534. /*
  5535.  * Get the name of a sign by its typenr.
  5536.  */
  5537.     char_u *
  5538. sign_typenr2name(typenr)
  5539.     int        typenr;
  5540. {
  5541.     sign_T    *sp;
  5542.  
  5543.     for (sp = first_sign; sp != NULL; sp = sp->sn_next)
  5544.     if (sp->sn_typenr == typenr)
  5545.         return sp->sn_name;
  5546.     return (char_u *)_("[Deleted]");
  5547. }
  5548.  
  5549. #endif
  5550.  
  5551. #if defined(FEAT_GUI) || defined(FEAT_CLIENTSERVER) || defined(PROTO)
  5552. /*
  5553.  * ":drop"
  5554.  */
  5555.     void
  5556. ex_drop(eap)
  5557.     exarg_T    *eap;
  5558. {
  5559.     int        split = FALSE;
  5560.  
  5561.     /* Check whether the current buffer is changed. If so, we will need
  5562.      * to split the current window or data could be lost.
  5563.      * We don't need to check if the 'hidden' option is set, as in this
  5564.      * case the buffer won't be lost.
  5565.      */
  5566.     if (!P_HID(curbuf))
  5567.     {
  5568.     ++emsg_off;
  5569.     split = check_changed(curbuf, TRUE, FALSE, FALSE, FALSE);
  5570.     --emsg_off;
  5571.     }
  5572.  
  5573.     /* Fake a ":snext" or ":next" command. */
  5574.     if (split)
  5575.     {
  5576.     eap->cmdidx = CMD_snext;
  5577.     eap->cmd[0] = 's';
  5578.     }
  5579.     else
  5580.     eap->cmdidx = CMD_next;
  5581.     ex_next(eap);
  5582. }
  5583. #endif
  5584.